From 48cce0d24aa36db084740691ea9e9e6803c9062a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Jan 2025 21:16:17 +0000 Subject: [PATCH] Bump the go-dependencies group across 1 directory with 21 updates Bumps the go-dependencies group with 16 updates in the / directory: | Package | From | To | | --- | --- | --- | | [github.com/aws/aws-sdk-go](https://github.com/aws/aws-sdk-go) | `1.55.5` | `1.55.6` | | [github.com/golang-migrate/migrate/v4](https://github.com/golang-migrate/migrate) | `4.18.1` | `4.18.2` | | [github.com/minio/minio-go/v7](https://github.com/minio/minio-go) | `7.0.82` | `7.0.84` | | [github.com/opentracing-contrib/go-grpc](https://github.com/opentracing-contrib/go-grpc) | `0.1.0` | `0.1.1` | | [github.com/prometheus/alertmanager](https://github.com/prometheus/alertmanager) | `0.27.0` | `0.28.0` | | [github.com/prometheus/common](https://github.com/prometheus/common) | `0.61.0` | `0.62.0` | | [go.etcd.io/etcd/api/v3](https://github.com/etcd-io/etcd) | `3.5.17` | `3.5.18` | | [go.etcd.io/etcd/client/pkg/v3](https://github.com/etcd-io/etcd) | `3.5.17` | `3.5.18` | | [go.etcd.io/etcd/client/v3](https://github.com/etcd-io/etcd) | `3.5.17` | `3.5.18` | | [go.opentelemetry.io/contrib/propagators/aws](https://github.com/open-telemetry/opentelemetry-go-contrib) | `1.33.0` | `1.34.0` | | [go.opentelemetry.io/otel/bridge/opentracing](https://github.com/open-telemetry/opentelemetry-go) | `1.33.0` | `1.34.0` | | [go.opentelemetry.io/otel/exporters/otlp/otlptrace](https://github.com/open-telemetry/opentelemetry-go) | `1.33.0` | `1.34.0` | | [go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc](https://github.com/open-telemetry/opentelemetry-go) | `1.33.0` | `1.34.0` | | [golang.org/x/time](https://github.com/golang/time) | `0.8.0` | `0.9.0` | | [github.com/tjhop/slog-gokit](https://github.com/tjhop/slog-gokit) | `0.1.2` | `0.1.3` | | [go.opentelemetry.io/collector/pdata](https://github.com/open-telemetry/opentelemetry-collector) | `1.22.0` | `1.24.0` | Updates `github.com/aws/aws-sdk-go` from 1.55.5 to 1.55.6 - [Release notes](https://github.com/aws/aws-sdk-go/releases) - [Changelog](https://github.com/aws/aws-sdk-go/blob/main/CHANGELOG_PENDING.md) - [Commits](https://github.com/aws/aws-sdk-go/compare/v1.55.5...v1.55.6) Updates `github.com/golang-migrate/migrate/v4` from 4.18.1 to 4.18.2 - [Release notes](https://github.com/golang-migrate/migrate/releases) - [Changelog](https://github.com/golang-migrate/migrate/blob/master/.goreleaser.yml) - [Commits](https://github.com/golang-migrate/migrate/compare/v4.18.1...v4.18.2) Updates `github.com/minio/minio-go/v7` from 7.0.82 to 7.0.84 - [Release notes](https://github.com/minio/minio-go/releases) - [Commits](https://github.com/minio/minio-go/compare/v7.0.82...v7.0.84) Updates `github.com/opentracing-contrib/go-grpc` from 0.1.0 to 0.1.1 - [Release notes](https://github.com/opentracing-contrib/go-grpc/releases) - [Commits](https://github.com/opentracing-contrib/go-grpc/compare/v0.1.0...v0.1.1) Updates `github.com/prometheus/alertmanager` from 0.27.0 to 0.28.0 - [Release notes](https://github.com/prometheus/alertmanager/releases) - [Changelog](https://github.com/prometheus/alertmanager/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus/alertmanager/compare/v0.27.0...v0.28.0) Updates `github.com/prometheus/common` from 0.61.0 to 0.62.0 - [Release notes](https://github.com/prometheus/common/releases) - [Changelog](https://github.com/prometheus/common/blob/main/RELEASE.md) - [Commits](https://github.com/prometheus/common/compare/v0.61.0...v0.62.0) Updates `go.etcd.io/etcd/api/v3` from 3.5.17 to 3.5.18 - [Release notes](https://github.com/etcd-io/etcd/releases) - [Commits](https://github.com/etcd-io/etcd/compare/v3.5.17...v3.5.18) Updates `go.etcd.io/etcd/client/pkg/v3` from 3.5.17 to 3.5.18 - [Release notes](https://github.com/etcd-io/etcd/releases) - [Commits](https://github.com/etcd-io/etcd/compare/v3.5.17...v3.5.18) Updates `go.etcd.io/etcd/client/v3` from 3.5.17 to 3.5.18 - [Release notes](https://github.com/etcd-io/etcd/releases) - [Commits](https://github.com/etcd-io/etcd/compare/v3.5.17...v3.5.18) Updates `go.opentelemetry.io/contrib/propagators/aws` from 1.33.0 to 1.34.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go-contrib/compare/v1.33.0...v1.34.0) Updates `go.opentelemetry.io/otel` from 1.33.0 to 1.34.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.33.0...v1.34.0) Updates `go.opentelemetry.io/otel/bridge/opentracing` from 1.33.0 to 1.34.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.33.0...v1.34.0) Updates `go.opentelemetry.io/otel/exporters/otlp/otlptrace` from 1.33.0 to 1.34.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.33.0...v1.34.0) Updates `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc` from 1.33.0 to 1.34.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.33.0...v1.34.0) Updates `go.opentelemetry.io/otel/sdk` from 1.33.0 to 1.34.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.33.0...v1.34.0) Updates `go.opentelemetry.io/otel/trace` from 1.33.0 to 1.34.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.33.0...v1.34.0) Updates `golang.org/x/net` from 0.33.0 to 0.34.0 - [Commits](https://github.com/golang/net/compare/v0.33.0...v0.34.0) Updates `golang.org/x/time` from 0.8.0 to 0.9.0 - [Commits](https://github.com/golang/time/compare/v0.8.0...v0.9.0) Updates `github.com/tjhop/slog-gokit` from 0.1.2 to 0.1.3 - [Release notes](https://github.com/tjhop/slog-gokit/releases) - [Changelog](https://github.com/tjhop/slog-gokit/blob/main/.goreleaser.yaml) - [Commits](https://github.com/tjhop/slog-gokit/compare/v0.1.2...v0.1.3) Updates `go.opentelemetry.io/collector/pdata` from 1.22.0 to 1.24.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-collector/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-collector/blob/main/CHANGELOG-API.md) - [Commits](https://github.com/open-telemetry/opentelemetry-collector/compare/pdata/v1.22.0...pdata/v1.24.0) Updates `google.golang.org/protobuf` from 1.36.1 to 1.36.3 --- updated-dependencies: - dependency-name: github.com/aws/aws-sdk-go dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-dependencies - dependency-name: github.com/golang-migrate/migrate/v4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-dependencies - dependency-name: github.com/minio/minio-go/v7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-dependencies - dependency-name: github.com/opentracing-contrib/go-grpc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-dependencies - dependency-name: github.com/prometheus/alertmanager dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: github.com/prometheus/common dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: go.etcd.io/etcd/api/v3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-dependencies - dependency-name: go.etcd.io/etcd/client/pkg/v3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-dependencies - dependency-name: go.etcd.io/etcd/client/v3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-dependencies - dependency-name: go.opentelemetry.io/contrib/propagators/aws dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: go.opentelemetry.io/otel dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: go.opentelemetry.io/otel/bridge/opentracing dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlptrace dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: go.opentelemetry.io/otel/sdk dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: go.opentelemetry.io/otel/trace dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: golang.org/x/time dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: github.com/tjhop/slog-gokit dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-dependencies - dependency-name: go.opentelemetry.io/collector/pdata dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: google.golang.org/protobuf dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-dependencies ... Signed-off-by: dependabot[bot] --- go.mod | 79 +- go.sum | 166 ++-- .../alecthomas/units/renovate.json5 | 4 + .../aws-sdk-go/aws/session/shared_config.go | 2 +- .../github.com/aws/aws-sdk-go/aws/version.go | 2 +- vendor/github.com/benbjohnson/clock/LICENSE | 21 - vendor/github.com/benbjohnson/clock/README.md | 105 --- vendor/github.com/benbjohnson/clock/clock.go | 422 --------- .../github.com/benbjohnson/clock/context.go | 86 -- vendor/github.com/coder/quartz/.gitignore | 1 + vendor/github.com/coder/quartz/LICENSE | 121 +++ vendor/github.com/coder/quartz/README.md | 632 ++++++++++++++ vendor/github.com/coder/quartz/clock.go | 43 + vendor/github.com/coder/quartz/mock.go | 661 ++++++++++++++ vendor/github.com/coder/quartz/real.go | 80 ++ vendor/github.com/coder/quartz/ticker.go | 75 ++ vendor/github.com/coder/quartz/timer.go | 81 ++ .../goccy/go-json/internal/decoder/compile.go | 18 +- .../internal/decoder/compile_norace.go | 1 + .../go-json/internal/decoder/compile_race.go | 1 + .../go-json/internal/encoder/compiler.go | 16 +- .../internal/encoder/compiler_norace.go | 1 + .../go-json/internal/encoder/compiler_race.go | 1 + .../goccy/go-json/internal/encoder/encoder.go | 5 + .../golang-migrate/migrate/v4/migrate.go | 4 +- .../grpc-gateway/v2/runtime/query.go | 2 +- .../github.com/jessevdk/go-flags/.travis.yml | 39 - vendor/github.com/jessevdk/go-flags/README.md | 5 +- .../github.com/jessevdk/go-flags/command.go | 11 + .../github.com/jessevdk/go-flags/convert.go | 17 +- vendor/github.com/jessevdk/go-flags/flags.go | 274 +++--- vendor/github.com/jessevdk/go-flags/help.go | 14 +- vendor/github.com/jessevdk/go-flags/ini.go | 14 +- vendor/github.com/jessevdk/go-flags/option.go | 4 +- .../jessevdk/go-flags/optstyle_other.go | 1 + .../jessevdk/go-flags/optstyle_windows.go | 1 + vendor/github.com/jessevdk/go-flags/parser.go | 15 +- .../github.com/jessevdk/go-flags/termsize.go | 3 +- .../jessevdk/go-flags/termsize_nosysioctl.go | 3 +- .../jessevdk/go-flags/termsize_windows.go | 1 + .../github.com/klauspost/cpuid/v2/README.md | 1 + vendor/github.com/klauspost/cpuid/v2/cpuid.go | 84 +- .../klauspost/cpuid/v2/cpuid_arm64.s | 10 + .../klauspost/cpuid/v2/detect_arm64.go | 3 +- .../klauspost/cpuid/v2/detect_ref.go | 2 + .../klauspost/cpuid/v2/detect_x86.go | 3 + .../klauspost/cpuid/v2/featureid_string.go | 440 +++++----- .../minio/minio-go/v7/api-copy-object.go | 2 +- .../minio/minio-go/v7/api-presigned.go | 2 +- vendor/github.com/minio/minio-go/v7/api.go | 22 +- .../minio/minio-go/v7/bucket-cache.go | 2 +- .../v7/pkg/credentials/assume_role.go | 43 +- .../minio-go/v7/pkg/credentials/chain.go | 18 + .../v7/pkg/credentials/credentials.go | 48 +- .../minio-go/v7/pkg/credentials/env_aws.go | 13 +- .../minio-go/v7/pkg/credentials/env_minio.go | 13 +- .../pkg/credentials/file_aws_credentials.go | 15 +- .../v7/pkg/credentials/file_minio_client.go | 15 +- .../minio-go/v7/pkg/credentials/iam_aws.go | 44 +- .../minio-go/v7/pkg/credentials/static.go | 5 + .../v7/pkg/credentials/sts_client_grants.go | 42 +- .../v7/pkg/credentials/sts_custom_identity.go | 36 +- .../v7/pkg/credentials/sts_ldap_identity.go | 40 +- .../v7/pkg/credentials/sts_tls_identity.go | 100 ++- .../v7/pkg/credentials/sts_web_identity.go | 42 +- .../minio/minio-go/v7/pkg/s3utils/utils.go | 20 +- vendor/github.com/minio/minio-go/v7/retry.go | 1 + .../github.com/prometheus/alertmanager/NOTICE | 5 - .../prometheus/alertmanager/api/api.go | 35 +- .../alertmanager/api/metrics/metrics.go | 2 +- .../alertmanager/api/v1_deprecation_router.go | 14 +- .../prometheus/alertmanager/api/v2/api.go | 79 +- .../alertgroup/get_alert_groups_parameters.go | 39 + .../prometheus/alertmanager/api/v2/compat.go | 13 +- .../api/v2/models/alert_status.go | 17 + .../alertmanager/api/v2/openapi.yaml | 10 + .../api/v2/restapi/embedded_spec.go | 32 +- .../alertgroup/get_alert_groups_parameters.go | 37 + .../alertgroup/get_alert_groups_urlbuilder.go | 9 + .../prometheus/alertmanager/api/v2/testing.go | 9 +- .../alertmanager/asset/assets_vfsdata.go | 12 +- .../alertmanager/cluster/channel.go | 21 +- .../alertmanager/cluster/cluster.go | 77 +- .../alertmanager/cluster/delegate.go | 38 +- .../alertmanager/cluster/tls_transport.go | 13 +- .../prometheus/alertmanager/config/config.go | 283 ++++-- .../alertmanager/config/coordinator.go | 23 +- .../alertmanager/config/notifiers.go | 270 ++++-- .../alertmanager/dispatch/dispatch.go | 115 +-- .../prometheus/alertmanager/dispatch/route.go | 22 +- .../featurecontrol/featurecontrol.go | 52 +- .../alertmanager/inhibit/inhibit.go | 15 +- .../{matchers => matcher}/compat/parse.go | 64 +- .../{matchers => matcher}/parse/lexer.go | 2 +- .../{matchers => matcher}/parse/parse.go | 8 +- .../{matchers => matcher}/parse/token.go | 0 .../prometheus/alertmanager/nflog/nflog.go | 42 +- .../alertmanager/notify/discord/discord.go | 44 +- .../alertmanager/notify/email/email.go | 33 +- .../alertmanager/notify/msteams/msteams.go | 9 +- .../prometheus/alertmanager/notify/notify.go | 153 ++-- .../alertmanager/notify/opsgenie/opsgenie.go | 11 +- .../notify/pagerduty/pagerduty.go | 15 +- .../alertmanager/notify/pushover/pushover.go | 18 +- .../alertmanager/notify/slack/slack.go | 9 +- .../prometheus/alertmanager/notify/sns/sns.go | 47 +- .../alertmanager/notify/telegram/telegram.go | 13 +- .../prometheus/alertmanager/notify/util.go | 13 +- .../notify/victorops/victorops.go | 9 +- .../alertmanager/notify/webex/webex.go | 14 +- .../alertmanager/notify/webhook/webhook.go | 40 +- .../alertmanager/notify/wechat/wechat.go | 11 +- .../alertmanager/pkg/labels/matcher.go | 2 +- .../alertmanager/pkg/labels/parse.go | 2 +- .../alertmanager/provider/mem/mem.go | 95 +- .../alertmanager/provider/provider.go | 2 +- .../alertmanager/silence/silence.go | 209 +++-- .../prometheus/alertmanager/store/store.go | 42 +- .../alertmanager/template/Dockerfile | 4 +- .../prometheus/alertmanager/template/Makefile | 2 +- .../alertmanager/template/default.tmpl | 59 ++ .../alertmanager/template/template.go | 15 + .../alertmanager/timeinterval/timeinterval.go | 14 +- .../prometheus/alertmanager/types/types.go | 142 ++- .../prometheus/alertmanager/ui/web.go | 4 +- .../prometheus/common/config/http_config.go | 22 +- .../common/expfmt/openmetrics_create.go | 4 +- .../prometheus/common/model/metric.go | 14 +- .../prometheus/common/promslog/slog.go | 201 +++++ .../exporter-toolkit/web/handler.go | 6 +- .../exporter-toolkit/web/landing_page.go | 4 + .../exporter-toolkit/web/tls_config.go | 21 +- vendor/github.com/rs/cors/cors.go | 16 +- .../github.com/rs/cors/internal/sortedset.go | 152 +++- vendor/github.com/rs/cors/utils.go | 9 - vendor/github.com/shurcooL/vfsgen/.travis.yml | 16 - vendor/github.com/shurcooL/vfsgen/README.md | 18 +- .../github.com/shurcooL/vfsgen/generator.go | 13 +- vendor/github.com/tjhop/slog-gokit/README.md | 13 +- vendor/github.com/tjhop/slog-gokit/handler.go | 34 +- .../go.etcd.io/etcd/api/v3/version/version.go | 2 +- vendor/go.etcd.io/etcd/client/v3/lease.go | 12 +- .../internal/data/protogen/logs/v1/logs.pb.go | 192 +++-- .../data/protogen/metrics/v1/metrics.pb.go | 12 +- .../profiles/v1development/profiles.pb.go | 815 +++++++----------- .../data/protogen/trace/v1/trace.pb.go | 6 +- vendor/go.opentelemetry.io/otel/CHANGELOG.md | 21 +- vendor/go.opentelemetry.io/otel/README.md | 2 +- vendor/go.opentelemetry.io/otel/RELEASING.md | 6 +- .../otlp/otlptrace/otlptracegrpc/client.go | 2 +- .../otel/exporters/otlp/otlptrace/version.go | 2 +- vendor/go.opentelemetry.io/otel/renovate.json | 6 - .../go.opentelemetry.io/otel/sdk/version.go | 2 +- vendor/go.opentelemetry.io/otel/version.go | 2 +- vendor/go.opentelemetry.io/otel/versions.yaml | 6 +- .../proto/otlp/trace/v1/trace.pb.go | 6 +- vendor/golang.org/x/crypto/pkcs12/crypto.go | 2 +- vendor/golang.org/x/net/http2/config.go | 2 +- vendor/golang.org/x/net/http2/config_go124.go | 2 +- vendor/golang.org/x/net/http2/transport.go | 13 +- .../x/sys/unix/syscall_dragonfly.go | 12 + .../golang.org/x/sys/windows/dll_windows.go | 11 +- .../x/tools/go/gcexportdata/gcexportdata.go | 119 ++- vendor/golang.org/x/tools/go/packages/doc.go | 15 +- .../x/tools/go/packages/external.go | 15 +- .../golang.org/x/tools/go/packages/golist.go | 43 +- .../x/tools/go/packages/loadmode_string.go | 70 +- .../x/tools/go/packages/packages.go | 391 +++++---- .../x/tools/go/types/objectpath/objectpath.go | 111 ++- .../x/tools/go/types/typeutil/callee.go | 68 ++ .../x/tools/go/types/typeutil/imports.go | 30 + .../x/tools/go/types/typeutil/map.go | 517 +++++++++++ .../tools/go/types/typeutil/methodsetcache.go | 71 ++ .../x/tools/go/types/typeutil/ui.go | 53 ++ .../x/tools/internal/aliases/aliases.go | 10 +- .../x/tools/internal/aliases/aliases_go121.go | 35 - .../x/tools/internal/aliases/aliases_go122.go | 33 +- .../x/tools/internal/gcimporter/bimport.go | 61 -- .../x/tools/internal/gcimporter/exportdata.go | 71 +- .../x/tools/internal/gcimporter/gcimporter.go | 69 +- .../x/tools/internal/gcimporter/iexport.go | 284 +++++- .../x/tools/internal/gcimporter/iimport.go | 43 +- .../internal/gcimporter/iimport_go122.go | 53 ++ .../internal/gcimporter/newInterface10.go | 22 - .../internal/gcimporter/newInterface11.go | 14 - .../tools/internal/gcimporter/predeclared.go | 91 ++ .../internal/gcimporter/support_go118.go | 34 - .../x/tools/internal/gcimporter/unified_no.go | 10 - .../tools/internal/gcimporter/unified_yes.go | 10 - .../tools/internal/gcimporter/ureader_yes.go | 44 +- .../x/tools/internal/gocommand/invoke.go | 18 +- .../internal/packagesinternal/packages.go | 2 - .../x/tools/internal/pkgbits/decoder.go | 34 +- .../x/tools/internal/pkgbits/encoder.go | 43 +- .../x/tools/internal/pkgbits/frames_go1.go | 21 - .../x/tools/internal/pkgbits/frames_go17.go | 28 - .../x/tools/internal/pkgbits/support.go | 2 +- .../x/tools/internal/pkgbits/sync.go | 23 + .../internal/pkgbits/syncmarker_string.go | 7 +- .../x/tools/internal/pkgbits/version.go | 85 ++ .../x/tools/internal/stdlib/manifest.go | 2 +- .../internal/tokeninternal/tokeninternal.go | 137 --- .../x/tools/internal/typeparams/common.go | 140 +++ .../x/tools/internal/typeparams/coretype.go | 150 ++++ .../x/tools/internal/typeparams/free.go | 131 +++ .../x/tools/internal/typeparams/normalize.go | 218 +++++ .../x/tools/internal/typeparams/termlist.go | 163 ++++ .../x/tools/internal/typeparams/typeterm.go | 169 ++++ .../x/tools/internal/typesinternal/element.go | 133 +++ .../tools/internal/typesinternal/errorcode.go | 8 +- .../x/tools/internal/typesinternal/recv.go | 8 +- .../x/tools/internal/typesinternal/types.go | 56 ++ .../tools/internal/typesinternal/zerovalue.go | 282 ++++++ .../x/tools/internal/versions/constraint.go | 13 - .../internal/versions/constraint_go121.go | 14 - .../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.go | 28 +- .../x/tools/internal/versions/types_go121.go | 30 - .../x/tools/internal/versions/types_go122.go | 41 - .../rpc/errdetails/error_details.pb.go | 128 +-- .../protobuf/encoding/protojson/decode.go | 2 +- .../protobuf/encoding/prototext/decode.go | 2 +- .../protobuf/internal/flags/flags.go | 5 + .../protobuf/internal/impl/codec_map.go | 14 +- .../protobuf/internal/impl/codec_map_go111.go | 38 - .../protobuf/internal/impl/codec_map_go112.go | 12 - .../protobuf/internal/impl/codec_message.go | 4 +- .../internal/impl/codec_message_opaque.go | 6 +- .../protobuf/internal/impl/convert_map.go | 2 +- .../protobuf/internal/impl/message.go | 12 +- .../protobuf/internal/impl/message_opaque.go | 36 +- .../internal/impl/message_reflect_field.go | 56 +- .../protobuf/internal/impl/pointer_unsafe.go | 2 +- .../protobuf/internal/version/version.go | 2 +- .../protobuf/proto/decode.go | 2 +- .../reflect/protodesc/desc_validate.go | 2 +- .../protobuf/reflect/protodesc/editions.go | 31 +- vendor/gopkg.in/telebot.v3/admin.go | 7 + vendor/gopkg.in/telebot.v3/api.go | 57 +- vendor/gopkg.in/telebot.v3/boost.go | 113 +++ vendor/gopkg.in/telebot.v3/bot.go | 211 ++++- vendor/gopkg.in/telebot.v3/callback.go | 9 + vendor/gopkg.in/telebot.v3/chat.go | 58 +- vendor/gopkg.in/telebot.v3/context.go | 41 +- vendor/gopkg.in/telebot.v3/errors.go | 9 + vendor/gopkg.in/telebot.v3/giveaway.go | 103 +++ vendor/gopkg.in/telebot.v3/inline.go | 42 + vendor/gopkg.in/telebot.v3/inline_types.go | 48 +- vendor/gopkg.in/telebot.v3/input_types.go | 6 +- vendor/gopkg.in/telebot.v3/markup.go | 22 +- vendor/gopkg.in/telebot.v3/media.go | 37 +- vendor/gopkg.in/telebot.v3/message.go | 264 +++++- vendor/gopkg.in/telebot.v3/options.go | 58 +- vendor/gopkg.in/telebot.v3/poll.go | 1 + vendor/gopkg.in/telebot.v3/poller.go | 23 +- vendor/gopkg.in/telebot.v3/react.go | 67 ++ vendor/gopkg.in/telebot.v3/sendable.go | 3 +- vendor/gopkg.in/telebot.v3/sticker.go | 306 +++++++ vendor/gopkg.in/telebot.v3/stickers.go | 212 ----- vendor/gopkg.in/telebot.v3/telebot.go | 3 + vendor/gopkg.in/telebot.v3/topic.go | 28 +- vendor/gopkg.in/telebot.v3/update.go | 42 +- vendor/gopkg.in/telebot.v3/web_app.go | 4 +- vendor/modules.txt | 114 +-- 267 files changed, 10342 insertions(+), 4497 deletions(-) delete mode 100644 vendor/github.com/benbjohnson/clock/LICENSE delete mode 100644 vendor/github.com/benbjohnson/clock/README.md delete mode 100644 vendor/github.com/benbjohnson/clock/clock.go delete mode 100644 vendor/github.com/benbjohnson/clock/context.go create mode 100644 vendor/github.com/coder/quartz/.gitignore create mode 100644 vendor/github.com/coder/quartz/LICENSE create mode 100644 vendor/github.com/coder/quartz/README.md create mode 100644 vendor/github.com/coder/quartz/clock.go create mode 100644 vendor/github.com/coder/quartz/mock.go create mode 100644 vendor/github.com/coder/quartz/real.go create mode 100644 vendor/github.com/coder/quartz/ticker.go create mode 100644 vendor/github.com/coder/quartz/timer.go delete mode 100644 vendor/github.com/jessevdk/go-flags/.travis.yml rename vendor/github.com/prometheus/alertmanager/{matchers => matcher}/compat/parse.go (65%) rename vendor/github.com/prometheus/alertmanager/{matchers => matcher}/parse/lexer.go (99%) rename vendor/github.com/prometheus/alertmanager/{matchers => matcher}/parse/parse.go (98%) rename vendor/github.com/prometheus/alertmanager/{matchers => matcher}/parse/token.go (100%) create mode 100644 vendor/github.com/prometheus/common/promslog/slog.go delete mode 100644 vendor/github.com/shurcooL/vfsgen/.travis.yml create mode 100644 vendor/golang.org/x/tools/go/types/typeutil/callee.go create mode 100644 vendor/golang.org/x/tools/go/types/typeutil/imports.go create mode 100644 vendor/golang.org/x/tools/go/types/typeutil/map.go create mode 100644 vendor/golang.org/x/tools/go/types/typeutil/methodsetcache.go create mode 100644 vendor/golang.org/x/tools/go/types/typeutil/ui.go delete mode 100644 vendor/golang.org/x/tools/internal/aliases/aliases_go121.go create mode 100644 vendor/golang.org/x/tools/internal/gcimporter/iimport_go122.go delete mode 100644 vendor/golang.org/x/tools/internal/gcimporter/newInterface10.go delete mode 100644 vendor/golang.org/x/tools/internal/gcimporter/newInterface11.go create mode 100644 vendor/golang.org/x/tools/internal/gcimporter/predeclared.go delete mode 100644 vendor/golang.org/x/tools/internal/gcimporter/support_go118.go delete mode 100644 vendor/golang.org/x/tools/internal/gcimporter/unified_no.go delete mode 100644 vendor/golang.org/x/tools/internal/gcimporter/unified_yes.go delete mode 100644 vendor/golang.org/x/tools/internal/pkgbits/frames_go1.go delete mode 100644 vendor/golang.org/x/tools/internal/pkgbits/frames_go17.go create mode 100644 vendor/golang.org/x/tools/internal/pkgbits/version.go delete mode 100644 vendor/golang.org/x/tools/internal/tokeninternal/tokeninternal.go create mode 100644 vendor/golang.org/x/tools/internal/typeparams/common.go create mode 100644 vendor/golang.org/x/tools/internal/typeparams/coretype.go create mode 100644 vendor/golang.org/x/tools/internal/typeparams/free.go create mode 100644 vendor/golang.org/x/tools/internal/typeparams/normalize.go create mode 100644 vendor/golang.org/x/tools/internal/typeparams/termlist.go create mode 100644 vendor/golang.org/x/tools/internal/typeparams/typeterm.go create mode 100644 vendor/golang.org/x/tools/internal/typesinternal/element.go create mode 100644 vendor/golang.org/x/tools/internal/typesinternal/zerovalue.go delete mode 100644 vendor/golang.org/x/tools/internal/versions/constraint.go delete mode 100644 vendor/golang.org/x/tools/internal/versions/constraint_go121.go delete mode 100644 vendor/golang.org/x/tools/internal/versions/toolchain.go delete mode 100644 vendor/golang.org/x/tools/internal/versions/toolchain_go119.go delete mode 100644 vendor/golang.org/x/tools/internal/versions/toolchain_go120.go delete mode 100644 vendor/golang.org/x/tools/internal/versions/toolchain_go121.go delete mode 100644 vendor/golang.org/x/tools/internal/versions/types_go121.go delete mode 100644 vendor/golang.org/x/tools/internal/versions/types_go122.go delete mode 100644 vendor/google.golang.org/protobuf/internal/impl/codec_map_go111.go delete mode 100644 vendor/google.golang.org/protobuf/internal/impl/codec_map_go112.go create mode 100644 vendor/gopkg.in/telebot.v3/boost.go create mode 100644 vendor/gopkg.in/telebot.v3/giveaway.go create mode 100644 vendor/gopkg.in/telebot.v3/react.go create mode 100644 vendor/gopkg.in/telebot.v3/sticker.go delete mode 100644 vendor/gopkg.in/telebot.v3/stickers.go diff --git a/go.mod b/go.mod index be6de1356e..3263a4cf00 100644 --- a/go.mod +++ b/go.mod @@ -4,10 +4,10 @@ go 1.23.0 require ( github.com/Masterminds/squirrel v1.5.4 - github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30 + github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b github.com/alicebob/miniredis/v2 v2.34.0 github.com/armon/go-metrics v0.4.1 - github.com/aws/aws-sdk-go v1.55.5 + github.com/aws/aws-sdk-go v1.55.6 github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 github.com/cortexproject/promqlsmith v0.0.0-20241121054008-8b48fe2471ef github.com/dustin/go-humanize v1.0.1 @@ -20,7 +20,7 @@ require ( github.com/go-redis/redis/v8 v8.11.5 github.com/gogo/protobuf v1.3.2 github.com/gogo/status v1.1.1 - github.com/golang-migrate/migrate/v4 v4.18.1 + github.com/golang-migrate/migrate/v4 v4.18.2 github.com/golang/protobuf v1.5.4 github.com/golang/snappy v0.0.4 github.com/gorilla/mux v1.8.1 @@ -33,17 +33,17 @@ require ( github.com/json-iterator/go v1.1.12 github.com/klauspost/compress v1.17.11 github.com/lib/pq v1.10.9 - github.com/minio/minio-go/v7 v7.0.82 + github.com/minio/minio-go/v7 v7.0.84 github.com/mitchellh/go-wordwrap v1.0.1 github.com/oklog/ulid v1.3.1 - github.com/opentracing-contrib/go-grpc v0.1.0 + github.com/opentracing-contrib/go-grpc v0.1.1 github.com/opentracing-contrib/go-stdlib v1.1.0 github.com/opentracing/opentracing-go v1.2.0 github.com/pkg/errors v0.9.1 - github.com/prometheus/alertmanager v0.27.0 + github.com/prometheus/alertmanager v0.28.0 github.com/prometheus/client_golang v1.20.5 github.com/prometheus/client_model v0.6.1 - github.com/prometheus/common v0.61.0 + github.com/prometheus/common v0.62.0 // Prometheus maps version 2.x.y to tags v0.x.y. github.com/prometheus/prometheus v0.55.1 github.com/segmentio/fasthash v1.0.3 @@ -55,21 +55,21 @@ require ( github.com/thanos-io/thanos v0.37.3-0.20250115144759-236777732278 github.com/uber/jaeger-client-go v2.30.0+incompatible github.com/weaveworks/common v0.0.0-20230728070032-dd9e68f319d5 - go.etcd.io/etcd/api/v3 v3.5.17 - go.etcd.io/etcd/client/pkg/v3 v3.5.17 - go.etcd.io/etcd/client/v3 v3.5.17 - go.opentelemetry.io/contrib/propagators/aws v1.33.0 - go.opentelemetry.io/otel v1.33.0 - go.opentelemetry.io/otel/bridge/opentracing v1.33.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 - go.opentelemetry.io/otel/sdk v1.33.0 - go.opentelemetry.io/otel/trace v1.33.0 + go.etcd.io/etcd/api/v3 v3.5.18 + go.etcd.io/etcd/client/pkg/v3 v3.5.18 + go.etcd.io/etcd/client/v3 v3.5.18 + go.opentelemetry.io/contrib/propagators/aws v1.34.0 + go.opentelemetry.io/otel v1.34.0 + go.opentelemetry.io/otel/bridge/opentracing v1.34.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 + go.opentelemetry.io/otel/sdk v1.34.0 + go.opentelemetry.io/otel/trace v1.34.0 go.uber.org/atomic v1.11.0 - golang.org/x/net v0.33.0 + golang.org/x/net v0.34.0 golang.org/x/sync v0.10.0 - golang.org/x/time v0.8.0 - google.golang.org/grpc v1.68.1 + golang.org/x/time v0.9.0 + google.golang.org/grpc v1.69.4 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -82,10 +82,10 @@ require ( github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 github.com/sercand/kuberesolver/v5 v5.1.1 - github.com/tjhop/slog-gokit v0.1.2 - go.opentelemetry.io/collector/pdata v1.22.0 + github.com/tjhop/slog-gokit v0.1.3 + go.opentelemetry.io/collector/pdata v1.24.0 golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 - google.golang.org/protobuf v1.36.1 + google.golang.org/protobuf v1.36.3 ) require ( @@ -120,6 +120,7 @@ require ( github.com/blang/semver/v4 v4.0.0 // indirect github.com/caio/go-tdigest v3.1.0+incompatible // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/coder/quartz v0.1.2 // indirect github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cristalhq/hedgedhttp v0.9.1 // indirect @@ -145,7 +146,7 @@ require ( github.com/go-openapi/runtime v0.28.0 // indirect github.com/go-openapi/spec v0.21.0 // indirect github.com/go-openapi/validate v0.24.0 // indirect - github.com/goccy/go-json v0.10.3 // indirect + github.com/goccy/go-json v0.10.4 // indirect github.com/gofrs/uuid v4.4.0+incompatible // indirect github.com/gogo/googleapis v1.4.0 // indirect github.com/golang-jwt/jwt/v5 v5.2.1 // indirect @@ -157,7 +158,7 @@ require ( github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect github.com/googleapis/gax-go/v2 v2.13.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect @@ -166,12 +167,12 @@ require ( github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/golang-lru v0.6.0 // indirect github.com/hashicorp/serf v0.10.1 // indirect - github.com/jessevdk/go-flags v1.5.0 // indirect + github.com/jessevdk/go-flags v1.6.1 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/julienschmidt/httprouter v1.3.0 // indirect - github.com/klauspost/cpuid/v2 v2.2.8 // indirect + github.com/klauspost/cpuid/v2 v2.2.9 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect @@ -196,15 +197,15 @@ require ( github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus-community/prom-label-proxy v0.8.1-0.20240127162815-c1195f9aabc0 // indirect github.com/prometheus/common/sigv4 v0.1.0 // indirect - github.com/prometheus/exporter-toolkit v0.12.0 // indirect + github.com/prometheus/exporter-toolkit v0.13.2 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/redis/rueidis v1.0.45-alpha.1 // indirect - github.com/rs/cors v1.11.0 // indirect + github.com/rs/cors v1.11.1 // indirect github.com/rs/xid v1.6.0 // indirect github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 // indirect github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c // indirect - github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 // indirect + github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/soheilhy/cmux v0.1.5 // indirect github.com/stretchr/objx v0.5.2 // indirect @@ -223,26 +224,26 @@ require ( go.opentelemetry.io/contrib/propagators/b3 v1.29.0 // indirect go.opentelemetry.io/contrib/propagators/jaeger v1.29.0 // indirect go.opentelemetry.io/contrib/propagators/ot v1.29.0 // indirect - go.opentelemetry.io/otel/metric v1.33.0 // indirect - go.opentelemetry.io/proto/otlp v1.4.0 // indirect + go.opentelemetry.io/otel/metric v1.34.0 // indirect + go.opentelemetry.io/proto/otlp v1.5.0 // indirect go.uber.org/goleak v1.3.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.21.0 // indirect go4.org/intern v0.0.0-20230525184215-6c62f75575cb // indirect go4.org/unsafe/assume-no-moving-gc v0.0.0-20230525183740-e7c30c78aeb2 // indirect - golang.org/x/crypto v0.31.0 // indirect - golang.org/x/mod v0.21.0 // indirect + golang.org/x/crypto v0.32.0 // indirect + golang.org/x/mod v0.22.0 // indirect golang.org/x/oauth2 v0.24.0 // indirect - golang.org/x/sys v0.28.0 // indirect + golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect - golang.org/x/tools v0.24.0 // indirect + golang.org/x/tools v0.28.0 // indirect gonum.org/v1/gonum v0.15.0 // indirect google.golang.org/api v0.195.0 // indirect google.golang.org/genproto v0.0.0-20240823204242-4ba0660f739c // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect - gopkg.in/telebot.v3 v3.2.1 // indirect + gopkg.in/telebot.v3 v3.3.8 // indirect k8s.io/apimachinery v0.31.1 // indirect k8s.io/client-go v0.31.0 // indirect k8s.io/klog/v2 v2.130.1 // indirect diff --git a/go.sum b/go.sum index 64dfdce3ba..73c0f06683 100644 --- a/go.sum +++ b/go.sum @@ -813,8 +813,8 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30 h1:t3eaIm0rUkzbrIewtiFmMK5RXHej2XnoXNhxVsAYUfg= -github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs= +github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b h1:mimo19zliBX/vSQ6PWWSL9lK8qwHozUj03+zLoEB8O0= +github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs= github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 h1:uvdUDbHQHO85qeSydJtItA4T55Pw6BtAejd0APRJOCE= github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= github.com/alicebob/miniredis/v2 v2.34.0 h1:mBFWMaJSNL9RwdGRyEDoAAv8OQc5UlEhLDQggTglU/0= @@ -839,8 +839,8 @@ github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgI github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= -github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= -github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/aws/aws-sdk-go v1.55.6 h1:cSg4pvZ3m8dgYcgqB97MrcdjUmZ1BeMYKUxMMB89IPk= +github.com/aws/aws-sdk-go v1.55.6/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= github.com/aws/aws-sdk-go-v2 v1.16.0/go.mod h1:lJYcuZZEHWNIb6ugJjbQY1fykdoobWbOS7kJYb4APoI= github.com/aws/aws-sdk-go-v2 v1.16.16 h1:M1fj4FE2lB4NzRb9Y0xdWsn2P0+2UHVxwKyOa4YJNjk= github.com/aws/aws-sdk-go-v2 v1.16.16/go.mod h1:SwiyXi/1zTUZ6KIAmLK5V5ll8SiURNUYOqTerZPaF9k= @@ -929,6 +929,8 @@ github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw= github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/coder/quartz v0.1.2 h1:PVhc9sJimTdKd3VbygXtS4826EOCpB1fXoRlLnCrE+s= +github.com/coder/quartz v0.1.2/go.mod h1:vsiCc+AHViMKH2CQpGIpFgdHIEQsxwm8yCscqKmzbRA= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= @@ -951,8 +953,8 @@ github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165 h1:BS21ZUJ/B5X2UV github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/dhui/dktest v0.4.3 h1:wquqUxAFdcUgabAVLvSCOKOlag5cIZuaOjYIBOWdsR0= -github.com/dhui/dktest v0.4.3/go.mod h1:zNK8IwktWzQRm6I/l2Wjp7MakiyaFWv4G1hjmodmMTs= +github.com/dhui/dktest v0.4.4 h1:+I4s6JRE1yGuqflzwqG+aIaMdgXIorCf5P98JnaAWa8= +github.com/dhui/dktest v0.4.4/go.mod h1:4+22R4lgsdAXrDyaH4Nqx2JEz2hLp49MqQmm9HLCQhM= github.com/digitalocean/godo v1.122.0 h1:ziytLQi8QKtDp2K1A+YrYl2dWLHLh2uaMzWvcz9HkKg= github.com/digitalocean/godo v1.122.0/go.mod h1:WQVH83OHUy6gC4gXpEVQKtxTd4L5oCp+5OialidkPLY= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= @@ -975,6 +977,10 @@ github.com/efficientgo/e2e v0.14.1-0.20230710114240-c316eb95ae5b h1:8VX23BNufsa4 github.com/efficientgo/e2e v0.14.1-0.20230710114240-c316eb95ae5b/go.mod h1:plsKU0YHE9uX+7utvr7SiDtVBSHJyEfHRO4UnUgDmts= github.com/efficientgo/tools/extkingpin v0.0.0-20220817170617-6c25e3b627dd h1:VaYzzXeUbC5fVheskcKVNOyJMEYD+HgrJNzIAg/mRIM= github.com/efficientgo/tools/extkingpin v0.0.0-20220817170617-6c25e3b627dd/go.mod h1:ZV0utlglOczUWv3ih2AbqPSoLoFzdplUYxwV62eZi6Q= +github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 h1:OJyUGMJTzHTd1XQp98QTaHernxMYzRaOasRir9hUlFQ= +github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ= +github.com/emersion/go-smtp v0.21.3 h1:7uVwagE8iPYE48WhNsng3RRpCUpFvNl39JGNSIyGVMY= +github.com/emersion/go-smtp v0.21.3/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= @@ -1083,8 +1089,8 @@ github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u1 github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= -github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM= +github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/goccy/go-yaml v1.9.5/go.mod h1:U/jl18uSupI5rdI2jmuCswEA2htH9eXfferR3KfscvA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= @@ -1102,8 +1108,8 @@ github.com/gogo/status v1.1.1 h1:DuHXlSFHNKqTQ+/ACf5Vs6r4X/dH2EgIzR9Vr+H65kg= github.com/gogo/status v1.1.1/go.mod h1:jpG3dM5QPcqu19Hg8lkUhBFBa3TcLs1DG7+2Jqci7oU= github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= -github.com/golang-migrate/migrate/v4 v4.18.1 h1:JML/k+t4tpHCpQTCAD62Nu43NUFzHY4CV3uAuvHGC+Y= -github.com/golang-migrate/migrate/v4 v4.18.1/go.mod h1:HAX6m3sQgcdO81tdjn5exv20+3Kb13cmGli1hrD6hks= +github.com/golang-migrate/migrate/v4 v4.18.2 h1:2VSCMz7x7mjyTXx3m2zPokOY82LTRgxK1yQYKo6wWQ8= +github.com/golang-migrate/migrate/v4 v4.18.2/go.mod h1:2CM6tJvn2kqPXwnXO/d3rAQYiyoIm180VsO8PRX6Rpk= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= @@ -1254,8 +1260,8 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFb github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 h1:TmHmbvxPmaegwhDubVz0lICL0J5Ka2vwTzhoePEXsGE= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0/go.mod h1:qztMSjm835F2bXf+5HKAPIS5qsmQDqZna/PgVt4rWtI= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ= github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= github.com/hashicorp/consul/api v1.31.0 h1:32BUNLembeSRek0G/ZAM6WNfdEwYdYo8oQ4+JoqGkNQ= github.com/hashicorp/consul/api v1.31.0/go.mod h1:2ZGIiXM3A610NmDULmCHd/aqBJj8CkMfOhswhOafxRg= @@ -1329,8 +1335,8 @@ github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/ionos-cloud/sdk-go/v6 v6.0.4 h1:4LoWeM7WtcDqYDjlntqQ3fD6XaENlCw2YqiVWkHQbNA= github.com/ionos-cloud/sdk-go/v6 v6.0.4/go.mod h1:UE3V/2DjnqD5doOqtjYqzJRMpI1RiwrvuuSEPX1pdnk= -github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= -github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= +github.com/jessevdk/go-flags v1.6.1 h1:Cvu5U8UGrLay1rZfv/zP7iLpSHGUZ/Ou68T0iX1bBK4= +github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= @@ -1362,8 +1368,8 @@ github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IX github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= -github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY= +github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8= github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b h1:udzkj9S/zlT5X367kqJis0QP7YMxobob6zhzq6Yre00= github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -1443,8 +1449,8 @@ github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcs github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= -github.com/minio/minio-go/v7 v7.0.82 h1:tWfICLhmp2aFPXL8Tli0XDTHj2VB/fNf0PC1f/i1gRo= -github.com/minio/minio-go/v7 v7.0.82/go.mod h1:84gmIilaX4zcvAWWzJ5Z1WI5axN+hAbM5w25xf8xvC0= +github.com/minio/minio-go/v7 v7.0.84 h1:D1HVmAF8JF8Bpi6IU4V9vIEj+8pc+xU88EWMs2yed0E= +github.com/minio/minio-go/v7 v7.0.84/go.mod h1:57YXpvc5l3rjPdhqNrDsvVlY0qPI6UTk1bflAe+9doY= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= @@ -1495,8 +1501,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= -github.com/opentracing-contrib/go-grpc v0.1.0 h1:9JHDtQXv6UL0tFF8KJB/4ApJgeOcaHp1h07d0PJjESc= -github.com/opentracing-contrib/go-grpc v0.1.0/go.mod h1:i3/jx/TvJZ/HKidtT4XGIi/NosUEpzS9xjVJctbKZzI= +github.com/opentracing-contrib/go-grpc v0.1.1 h1:Ws7IN1zyiL1DFqKQPhRXuKe5pLYzMfdxnC1qtajE2PE= +github.com/opentracing-contrib/go-grpc v0.1.1/go.mod h1:Nu6sz+4zzgxXu8rvKfnwjBEmHsuhTigxRwV2RhELrS8= github.com/opentracing-contrib/go-stdlib v1.1.0 h1:cZBWc4pA4e65tqTJddbflK435S0tDImj6c9BMvkdUH0= github.com/opentracing-contrib/go-stdlib v1.1.0/go.mod h1:S0p+X9p6dcBkoMTL+Qq2VOvxKs9ys5PpYWXWqlCS0bQ= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -1534,8 +1540,8 @@ github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndr github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/prometheus-community/prom-label-proxy v0.8.1-0.20240127162815-c1195f9aabc0 h1:owfYHh79h8Y5HvNMGyww+DaVwo10CKiRW1RQrrZzIwg= github.com/prometheus-community/prom-label-proxy v0.8.1-0.20240127162815-c1195f9aabc0/go.mod h1:rT989D4UtOcfd9tVqIZRVIM8rkg+9XbreBjFNEKXvVI= -github.com/prometheus/alertmanager v0.27.0 h1:V6nTa2J5V4s8TG4C4HtrBP/WNSebCCTYGGv4qecA/+I= -github.com/prometheus/alertmanager v0.27.0/go.mod h1:8Ia/R3urPmbzJ8OsdvmZvIprDwvwmYCmUbwBL+jlPOE= +github.com/prometheus/alertmanager v0.28.0 h1:sLN+6HhZet8hrbmGHLAHWsTXgZSVCvq9Ix3U3wvivqc= +github.com/prometheus/alertmanager v0.28.0/go.mod h1:/okSnb2LlodbMlRoOWQEKtqI/coOo2NKZDm2Hu9QHLQ= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= @@ -1558,12 +1564,12 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ= -github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s= +github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= +github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= github.com/prometheus/common/sigv4 v0.1.0 h1:qoVebwtwwEhS85Czm2dSROY5fTo2PAPEVdDeppTwGX4= github.com/prometheus/common/sigv4 v0.1.0/go.mod h1:2Jkxxk9yYvCkE5G1sQT7GuEXm57JrvHu9k5YwTjsNtI= -github.com/prometheus/exporter-toolkit v0.12.0 h1:DkE5RcEZR3lQA2QD5JLVQIf41dFKNsVMXFhgqcif7fo= -github.com/prometheus/exporter-toolkit v0.12.0/go.mod h1:fQH0KtTn0yrrS0S82kqppRjDDiwMfIQUwT+RBRRhwUc= +github.com/prometheus/exporter-toolkit v0.13.2 h1:Z02fYtbqTMy2i/f+xZ+UK5jy/bl1Ex3ndzh06T/Q9DQ= +github.com/prometheus/exporter-toolkit v0.13.2/go.mod h1:tCqnfx21q6qN1KA4U3Bfb8uWzXfijIrJz3/kTIqMV7g= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= @@ -1583,8 +1589,8 @@ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= -github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po= -github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= @@ -1603,8 +1609,8 @@ github.com/sercand/kuberesolver/v5 v5.1.1 h1:CYH+d67G0sGBj7q5wLK61yzqJJ8gLLC8aep github.com/sercand/kuberesolver/v5 v5.1.1/go.mod h1:Fs1KbKhVRnB2aDWN12NjKCB+RgYMWZJ294T3BtmVCpQ= github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c h1:aqg5Vm5dwtvL+YgDpBcK1ITf3o96N/K7/wsRXQnUTEs= github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c/go.mod h1:owqhoLW1qZoYLZzLnBw+QkPP9WZnjlSWihhxAJC1+/M= -github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 h1:pXY9qYc/MP5zdvqWEUH6SjNiu7VhSjuVFTFiTcphaLU= -github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= +github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92 h1:OfRzdxCzDhp+rsKWXuOO2I/quKMJ/+TQwVbIP/gltZg= +github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92/go.mod h1:7/OT02F6S6I7v6WXb+IjhMuZEYfH/RJ5RwEWnEo5BMg= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= @@ -1659,8 +1665,8 @@ github.com/thanos-io/promql-engine v0.0.0-20250110162513-14f995518af3 h1:feQKBuP github.com/thanos-io/promql-engine v0.0.0-20250110162513-14f995518af3/go.mod h1:wx0JlRZtsB2S10JYUgeg5GqLfMxw31SzArP+28yyE00= github.com/thanos-io/thanos v0.37.3-0.20250115144759-236777732278 h1:HkZohVruRD0ENAXZIl2qDcpblbMok++jb3zHvjUeQfg= github.com/thanos-io/thanos v0.37.3-0.20250115144759-236777732278/go.mod h1:DvlfyJhdYeufGbw3z6VQuDpGh2Q46/XvalnmEtQOf/0= -github.com/tjhop/slog-gokit v0.1.2 h1:pmQI4SvU9h4gA0vIQsdhJQSqQg4mOmsPykG2/PM3j1I= -github.com/tjhop/slog-gokit v0.1.2/go.mod h1:8fhlcp8C8ELbg3GCyKv06tgt4B5sDq2P1r2DQAu1HuM= +github.com/tjhop/slog-gokit v0.1.3 h1:6SdexP3UIeg93KLFeiM1Wp1caRwdTLgsD/THxBUy1+o= +github.com/tjhop/slog-gokit v0.1.3/go.mod h1:Bbu5v2748qpAWH7k6gse/kw3076IJf6owJmh7yArmJs= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= @@ -1686,15 +1692,15 @@ github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaD github.com/zhangyunhao116/umap v0.0.0-20221211160557-cb7705fafa39 h1:D3ltj0b2c2FgUacKrB1pWGgwrUyCESY9W8XYYQ5sqY8= github.com/zhangyunhao116/umap v0.0.0-20221211160557-cb7705fafa39/go.mod h1:r86X1CnsDRrOeLtJlqRWdELPWpkcf933GTlojQlifQw= go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= -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/api/v3 v3.5.18 h1:Q4oDAKnmwqTo5lafvB+afbgCDF7E35E4EYV2g+FNGhs= +go.etcd.io/etcd/api/v3 v3.5.18/go.mod h1:uY03Ob2H50077J7Qq0DeehjM/A9S8PhVfbQ1mSaMopU= go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -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/pkg/v3 v3.5.18 h1:mZPOYw4h8rTk7TeJ5+3udUkfVGBqc+GCjOJYd68QgNM= +go.etcd.io/etcd/client/pkg/v3 v3.5.18/go.mod h1:BxVf2o5wXG9ZJV+/Cu7QNUiJYk4A29sAhoI5tIRsCu4= go.etcd.io/etcd/client/v2 v2.305.4/go.mod h1:Ud+VUwIi9/uQHOMA+4ekToJ12lTxlv0zB/+DHwTGEbU= go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY= -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.etcd.io/etcd/client/v3 v3.5.18 h1:nvvYmNHGumkDjZhTHgVU36A9pykGa2K4lAJ0yY7hcXA= +go.etcd.io/etcd/client/v3 v3.5.18/go.mod h1:kmemwOsPU9broExyhYsBxX4spCTDX3yLgPMWtpBXG6E= go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80= go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -1708,8 +1714,8 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/collector/pdata v1.22.0 h1:3yhjL46NLdTMoP8rkkcE9B0pzjf2973crn0KKhX5UrI= -go.opentelemetry.io/collector/pdata v1.22.0/go.mod h1:nLLf6uDg8Kn5g3WNZwGyu8+kf77SwOqQvMTb5AXEbEY= +go.opentelemetry.io/collector/pdata v1.24.0 h1:D6j92eAzmAbQgivNBUnt8r9juOl8ugb+ihYynoFZIEg= +go.opentelemetry.io/collector/pdata v1.24.0/go.mod h1:cf3/W9E/uIvPS4MR26SnMFJhraUCattzzM6qusuONuc= go.opentelemetry.io/collector/semconv v0.108.1 h1:Txk9tauUnamZaxS5vlf1O0uZ4VD6nioRBR0nX8L/fU4= go.opentelemetry.io/collector/semconv v0.108.1/go.mod h1:zCJ5njhWpejR+A40kiEoeFm1xq1uzyZwMnRNX6/D82A= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= @@ -1718,34 +1724,34 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+n go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= go.opentelemetry.io/contrib/propagators/autoprop v0.54.0 h1:h/O1OcNbqrFilsMKfG6MJWWpx8gzCDfn9D+1W7lU3lE= go.opentelemetry.io/contrib/propagators/autoprop v0.54.0/go.mod h1:VIaPlErTgbng1UhrMA4N6Yy+f94PLA/qRPOCMATdoCs= -go.opentelemetry.io/contrib/propagators/aws v1.33.0 h1:MefPfPIut0IxEiQRK1qVv5AFADBOwizl189+m7QhpFg= -go.opentelemetry.io/contrib/propagators/aws v1.33.0/go.mod h1:VB6xPo12uW/PezOqtA/cY2/DiAGYshnhID606wC9NEY= +go.opentelemetry.io/contrib/propagators/aws v1.34.0 h1:pv/Yi44N2BM1Kyl6wxO6bTiwcxUA7Deog3Rc7NO9ITE= +go.opentelemetry.io/contrib/propagators/aws v1.34.0/go.mod h1:1aF3HFtAyIi+B2xJHOdKQcNz+bcDS+JLAZjsohcW1P4= go.opentelemetry.io/contrib/propagators/b3 v1.29.0 h1:hNjyoRsAACnhoOLWupItUjABzeYmX3GTTZLzwJluJlk= go.opentelemetry.io/contrib/propagators/b3 v1.29.0/go.mod h1:E76MTitU1Niwo5NSN+mVxkyLu4h4h7Dp/yh38F2WuIU= go.opentelemetry.io/contrib/propagators/jaeger v1.29.0 h1:+YPiqF5rR6PqHBlmEFLPumbSP0gY0WmCGFayXRcCLvs= go.opentelemetry.io/contrib/propagators/jaeger v1.29.0/go.mod h1:6PD7q7qquWSp3Z4HeM3e/2ipRubaY1rXZO8NIHVDZjs= go.opentelemetry.io/contrib/propagators/ot v1.29.0 h1:CaJU78FvXrA6ajjp1dOdcABBEjh529+hl396RTqc2LQ= go.opentelemetry.io/contrib/propagators/ot v1.29.0/go.mod h1:Sc0omwLb4eptUhwOAfYXfmPmErHPu2HV6vkeDge/3sY= -go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw= -go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I= -go.opentelemetry.io/otel/bridge/opentracing v1.33.0 h1:eH88qvKdY7ns7Xu6WlJBQNOzZ3MVvBR6tEl2euaYS9w= -go.opentelemetry.io/otel/bridge/opentracing v1.33.0/go.mod h1:FNai/nhRSn/kHyv+V1zaf/30BU8hO/DXo0MvV0PaUS8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 h1:Vh5HayB/0HHfOQA7Ctx69E/Y/DcQSMPpKANYVMQ7fBA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0/go.mod h1:cpgtDBaqD/6ok/UG0jT15/uKjAY8mRA53diogHBg3UI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 h1:5pojmb1U1AogINhN3SurB+zm/nIcusopeBNp42f45QM= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0/go.mod h1:57gTHJSE5S1tqg+EKsLPlTWhpHMsWlVmer+LA926XiA= -go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ= -go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M= -go.opentelemetry.io/otel/sdk v1.33.0 h1:iax7M131HuAm9QkZotNHEfstof92xM+N8sr3uHXc2IM= -go.opentelemetry.io/otel/sdk v1.33.0/go.mod h1:A1Q5oi7/9XaMlIWzPSxLRWOI8nG3FnzHJNbiENQuihM= -go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s= -go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck= +go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= +go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= +go.opentelemetry.io/otel/bridge/opentracing v1.34.0 h1:QwIV7Mh/1MNFS56EgWI8p+nAAx/40DIQqgO0qXkX5NY= +go.opentelemetry.io/otel/bridge/opentracing v1.34.0/go.mod h1:4GYWm9bVsi+4+qJFpmBjFuuuMTVgxxIMfzekizbZ+o0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= +go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= +go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= +go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= +go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= +go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= +go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= -go.opentelemetry.io/proto/otlp v1.4.0 h1:TA9WRvW6zMwP+Ssb6fLoUIuirti1gGbP28GcKG1jgeg= -go.opentelemetry.io/proto/otlp v1.4.0/go.mod h1:PPBWZIP98o2ElSqI35IHfu7hIhSwvc5N38Jw8pXuGFY= +go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= +go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= go.uber.org/atomic v1.7.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= @@ -1788,8 +1794,8 @@ golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1m golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1851,8 +1857,8 @@ golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1925,8 +1931,8 @@ golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -2087,8 +2093,8 @@ golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.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.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -2105,8 +2111,8 @@ golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= -golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= -golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= +golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -2134,8 +2140,8 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -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/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= +golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -2204,8 +2210,8 @@ golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= -golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= -golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= +golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= +golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= 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= @@ -2453,8 +2459,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go. google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU= -google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q= -google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08= +google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA= +google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o= google.golang.org/genproto/googleapis/bytestream v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:ylj+BE99M198VPbBh6A8d9n3w8fChvyLK3wwBOjXBFA= google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234015-3fc162c6f38a/go.mod h1:xURIpW9ES5+/GZhnV6beoEtxQrnkRGIfP5VQG2tCBLc= google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= @@ -2468,8 +2474,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5/go. google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240521202816-d264139d666e/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 h1:8ZmaLZE4XWrtU3MyClkYqqtl6Oegr3235h7jxsDyqCY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= @@ -2494,8 +2500,8 @@ google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= -google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= +google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= 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-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -2507,8 +2513,8 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/telebot.v3 v3.2.1 h1:3I4LohaAyJBiivGmkfB+CiVu7QFOWkuZ4+KHgO/G3rs= -gopkg.in/telebot.v3 v3.2.1/go.mod h1:GJKwwWqp9nSkIVN51eRKU78aB5f5OnQuWdwiIZfPbko= +gopkg.in/telebot.v3 v3.3.8 h1:uVDGjak9l824FN9YARWUHMsiNZnlohAVwUycw21k6t8= +gopkg.in/telebot.v3 v3.3.8/go.mod h1:1mlbqcLTVSfK9dx7fdp+Nb5HZsy4LLPtpZTKmwhwtzM= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/alecthomas/units/renovate.json5 b/vendor/github.com/alecthomas/units/renovate.json5 index 897864b852..6bb4acde94 100644 --- a/vendor/github.com/alecthomas/units/renovate.json5 +++ b/vendor/github.com/alecthomas/units/renovate.json5 @@ -8,4 +8,8 @@ "group:allNonMajor", "schedule:earlyMondays", // Run once a week. ], + postUpdateOptions: [ + "gomodTidy", + "gomodUpdateImportPaths" + ] } diff --git a/vendor/github.com/aws/aws-sdk-go/aws/session/shared_config.go b/vendor/github.com/aws/aws-sdk-go/aws/session/shared_config.go index f3ce8183dd..2945185b0b 100644 --- a/vendor/github.com/aws/aws-sdk-go/aws/session/shared_config.go +++ b/vendor/github.com/aws/aws-sdk-go/aws/session/shared_config.go @@ -349,7 +349,7 @@ func (cfg *sharedConfig) setFromIniFiles(profiles map[string]struct{}, profile s if cfg.hasSSOTokenProviderConfiguration() { skippedFiles = 0 for _, f := range files { - section, ok := f.IniData.GetSection(fmt.Sprintf(ssoSectionPrefix + strings.TrimSpace(cfg.SSOSessionName))) + section, ok := f.IniData.GetSection(ssoSectionPrefix + strings.TrimSpace(cfg.SSOSessionName)) if ok { var ssoSession ssoSession ssoSession.setFromIniSection(section) diff --git a/vendor/github.com/aws/aws-sdk-go/aws/version.go b/vendor/github.com/aws/aws-sdk-go/aws/version.go index d15e3c84c0..7ab65bae79 100644 --- a/vendor/github.com/aws/aws-sdk-go/aws/version.go +++ b/vendor/github.com/aws/aws-sdk-go/aws/version.go @@ -5,4 +5,4 @@ package aws const SDKName = "aws-sdk-go" // SDKVersion is the version of this SDK -const SDKVersion = "1.55.5" +const SDKVersion = "1.55.6" diff --git a/vendor/github.com/benbjohnson/clock/LICENSE b/vendor/github.com/benbjohnson/clock/LICENSE deleted file mode 100644 index ce212cb1ce..0000000000 --- a/vendor/github.com/benbjohnson/clock/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 Ben Johnson - -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/benbjohnson/clock/README.md b/vendor/github.com/benbjohnson/clock/README.md deleted file mode 100644 index 4f1f82fc6d..0000000000 --- a/vendor/github.com/benbjohnson/clock/README.md +++ /dev/null @@ -1,105 +0,0 @@ -clock -===== - -[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/mod/github.com/benbjohnson/clock) - -Clock is a small library for mocking time in Go. It provides an interface -around the standard library's [`time`][time] package so that the application -can use the realtime clock while tests can use the mock clock. - -The module is currently maintained by @djmitche. - -[time]: https://pkg.go.dev/github.com/benbjohnson/clock - -## Usage - -### Realtime Clock - -Your application can maintain a `Clock` variable that will allow realtime and -mock clocks to be interchangeable. For example, if you had an `Application` type: - -```go -import "github.com/benbjohnson/clock" - -type Application struct { - Clock clock.Clock -} -``` - -You could initialize it to use the realtime clock like this: - -```go -var app Application -app.Clock = clock.New() -... -``` - -Then all timers and time-related functionality should be performed from the -`Clock` variable. - - -### Mocking time - -In your tests, you will want to use a `Mock` clock: - -```go -import ( - "testing" - - "github.com/benbjohnson/clock" -) - -func TestApplication_DoSomething(t *testing.T) { - mock := clock.NewMock() - app := Application{Clock: mock} - ... -} -``` - -Now that you've initialized your application to use the mock clock, you can -adjust the time programmatically. The mock clock always starts from the Unix -epoch (midnight UTC on Jan 1, 1970). - - -### Controlling time - -The mock clock provides the same functions that the standard library's `time` -package provides. For example, to find the current time, you use the `Now()` -function: - -```go -mock := clock.NewMock() - -// Find the current time. -mock.Now().UTC() // 1970-01-01 00:00:00 +0000 UTC - -// Move the clock forward. -mock.Add(2 * time.Hour) - -// Check the time again. It's 2 hours later! -mock.Now().UTC() // 1970-01-01 02:00:00 +0000 UTC -``` - -Timers and Tickers are also controlled by this same mock clock. They will only -execute when the clock is moved forward: - -```go -mock := clock.NewMock() -count := 0 - -// Kick off a timer to increment every 1 mock second. -go func() { - ticker := mock.Ticker(1 * time.Second) - for { - <-ticker.C - count++ - } -}() -runtime.Gosched() - -// Move the clock forward 10 seconds. -mock.Add(10 * time.Second) - -// This prints 10. -fmt.Println(count) -``` diff --git a/vendor/github.com/benbjohnson/clock/clock.go b/vendor/github.com/benbjohnson/clock/clock.go deleted file mode 100644 index 14ddc0795b..0000000000 --- a/vendor/github.com/benbjohnson/clock/clock.go +++ /dev/null @@ -1,422 +0,0 @@ -package clock - -import ( - "context" - "sort" - "sync" - "time" -) - -// Re-export of time.Duration -type Duration = time.Duration - -// Clock represents an interface to the functions in the standard library time -// package. Two implementations are available in the clock package. The first -// is a real-time clock which simply wraps the time package's functions. The -// second is a mock clock which will only change when -// programmatically adjusted. -type Clock interface { - After(d time.Duration) <-chan time.Time - AfterFunc(d time.Duration, f func()) *Timer - Now() time.Time - Since(t time.Time) time.Duration - Until(t time.Time) time.Duration - Sleep(d time.Duration) - Tick(d time.Duration) <-chan time.Time - Ticker(d time.Duration) *Ticker - Timer(d time.Duration) *Timer - WithDeadline(parent context.Context, d time.Time) (context.Context, context.CancelFunc) - WithTimeout(parent context.Context, t time.Duration) (context.Context, context.CancelFunc) -} - -// New returns an instance of a real-time clock. -func New() Clock { - return &clock{} -} - -// clock implements a real-time clock by simply wrapping the time package functions. -type clock struct{} - -func (c *clock) After(d time.Duration) <-chan time.Time { return time.After(d) } - -func (c *clock) AfterFunc(d time.Duration, f func()) *Timer { - return &Timer{timer: time.AfterFunc(d, f)} -} - -func (c *clock) Now() time.Time { return time.Now() } - -func (c *clock) Since(t time.Time) time.Duration { return time.Since(t) } - -func (c *clock) Until(t time.Time) time.Duration { return time.Until(t) } - -func (c *clock) Sleep(d time.Duration) { time.Sleep(d) } - -func (c *clock) Tick(d time.Duration) <-chan time.Time { return time.Tick(d) } - -func (c *clock) Ticker(d time.Duration) *Ticker { - t := time.NewTicker(d) - return &Ticker{C: t.C, ticker: t} -} - -func (c *clock) Timer(d time.Duration) *Timer { - t := time.NewTimer(d) - return &Timer{C: t.C, timer: t} -} - -func (c *clock) WithDeadline(parent context.Context, d time.Time) (context.Context, context.CancelFunc) { - return context.WithDeadline(parent, d) -} - -func (c *clock) WithTimeout(parent context.Context, t time.Duration) (context.Context, context.CancelFunc) { - return context.WithTimeout(parent, t) -} - -// Mock represents a mock clock that only moves forward programmically. -// It can be preferable to a real-time clock when testing time-based functionality. -type Mock struct { - // mu protects all other fields in this struct, and the data that they - // point to. - mu sync.Mutex - - now time.Time // current time - timers clockTimers // tickers & timers -} - -// NewMock returns an instance of a mock clock. -// The current time of the mock clock on initialization is the Unix epoch. -func NewMock() *Mock { - return &Mock{now: time.Unix(0, 0)} -} - -// Add moves the current time of the mock clock forward by the specified duration. -// This should only be called from a single goroutine at a time. -func (m *Mock) Add(d time.Duration) { - // Calculate the final current time. - m.mu.Lock() - t := m.now.Add(d) - m.mu.Unlock() - - // Continue to execute timers until there are no more before the new time. - for { - if !m.runNextTimer(t) { - break - } - } - - // Ensure that we end with the new time. - m.mu.Lock() - m.now = t - m.mu.Unlock() - - // Give a small buffer to make sure that other goroutines get handled. - gosched() -} - -// Set sets the current time of the mock clock to a specific one. -// This should only be called from a single goroutine at a time. -func (m *Mock) Set(t time.Time) { - // Continue to execute timers until there are no more before the new time. - for { - if !m.runNextTimer(t) { - break - } - } - - // Ensure that we end with the new time. - m.mu.Lock() - m.now = t - m.mu.Unlock() - - // Give a small buffer to make sure that other goroutines get handled. - gosched() -} - -// WaitForAllTimers sets the clock until all timers are expired -func (m *Mock) WaitForAllTimers() time.Time { - // Continue to execute timers until there are no more - for { - m.mu.Lock() - if len(m.timers) == 0 { - m.mu.Unlock() - return m.Now() - } - - sort.Sort(m.timers) - next := m.timers[len(m.timers)-1].Next() - m.mu.Unlock() - m.Set(next) - } -} - -// runNextTimer executes the next timer in chronological order and moves the -// current time to the timer's next tick time. The next time is not executed if -// its next time is after the max time. Returns true if a timer was executed. -func (m *Mock) runNextTimer(max time.Time) bool { - m.mu.Lock() - - // Sort timers by time. - sort.Sort(m.timers) - - // If we have no more timers then exit. - if len(m.timers) == 0 { - m.mu.Unlock() - return false - } - - // Retrieve next timer. Exit if next tick is after new time. - t := m.timers[0] - if t.Next().After(max) { - m.mu.Unlock() - return false - } - - // Move "now" forward and unlock clock. - m.now = t.Next() - now := m.now - m.mu.Unlock() - - // Execute timer. - t.Tick(now) - return true -} - -// After waits for the duration to elapse and then sends the current time on the returned channel. -func (m *Mock) After(d time.Duration) <-chan time.Time { - return m.Timer(d).C -} - -// AfterFunc waits for the duration to elapse and then executes a function in its own goroutine. -// A Timer is returned that can be stopped. -func (m *Mock) AfterFunc(d time.Duration, f func()) *Timer { - m.mu.Lock() - defer m.mu.Unlock() - ch := make(chan time.Time, 1) - t := &Timer{ - c: ch, - fn: f, - mock: m, - next: m.now.Add(d), - stopped: false, - } - m.timers = append(m.timers, (*internalTimer)(t)) - return t -} - -// Now returns the current wall time on the mock clock. -func (m *Mock) Now() time.Time { - m.mu.Lock() - defer m.mu.Unlock() - return m.now -} - -// Since returns time since `t` using the mock clock's wall time. -func (m *Mock) Since(t time.Time) time.Duration { - return m.Now().Sub(t) -} - -// Until returns time until `t` using the mock clock's wall time. -func (m *Mock) Until(t time.Time) time.Duration { - return t.Sub(m.Now()) -} - -// Sleep pauses the goroutine for the given duration on the mock clock. -// The clock must be moved forward in a separate goroutine. -func (m *Mock) Sleep(d time.Duration) { - <-m.After(d) -} - -// Tick is a convenience function for Ticker(). -// It will return a ticker channel that cannot be stopped. -func (m *Mock) Tick(d time.Duration) <-chan time.Time { - return m.Ticker(d).C -} - -// Ticker creates a new instance of Ticker. -func (m *Mock) Ticker(d time.Duration) *Ticker { - m.mu.Lock() - defer m.mu.Unlock() - ch := make(chan time.Time, 1) - t := &Ticker{ - C: ch, - c: ch, - mock: m, - d: d, - next: m.now.Add(d), - } - m.timers = append(m.timers, (*internalTicker)(t)) - return t -} - -// Timer creates a new instance of Timer. -func (m *Mock) Timer(d time.Duration) *Timer { - m.mu.Lock() - ch := make(chan time.Time, 1) - t := &Timer{ - C: ch, - c: ch, - mock: m, - next: m.now.Add(d), - stopped: false, - } - m.timers = append(m.timers, (*internalTimer)(t)) - now := m.now - m.mu.Unlock() - m.runNextTimer(now) - return t -} - -// removeClockTimer removes a timer from m.timers. m.mu MUST be held -// when this method is called. -func (m *Mock) removeClockTimer(t clockTimer) { - for i, timer := range m.timers { - if timer == t { - copy(m.timers[i:], m.timers[i+1:]) - m.timers[len(m.timers)-1] = nil - m.timers = m.timers[:len(m.timers)-1] - break - } - } - sort.Sort(m.timers) -} - -// clockTimer represents an object with an associated start time. -type clockTimer interface { - Next() time.Time - Tick(time.Time) -} - -// clockTimers represents a list of sortable timers. -type clockTimers []clockTimer - -func (a clockTimers) Len() int { return len(a) } -func (a clockTimers) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a clockTimers) Less(i, j int) bool { return a[i].Next().Before(a[j].Next()) } - -// Timer represents a single event. -// The current time will be sent on C, unless the timer was created by AfterFunc. -type Timer struct { - C <-chan time.Time - c chan time.Time - timer *time.Timer // realtime impl, if set - next time.Time // next tick time - mock *Mock // mock clock, if set - fn func() // AfterFunc function, if set - stopped bool // True if stopped, false if running -} - -// Stop turns off the ticker. -func (t *Timer) Stop() bool { - if t.timer != nil { - return t.timer.Stop() - } - - t.mock.mu.Lock() - registered := !t.stopped - t.mock.removeClockTimer((*internalTimer)(t)) - t.stopped = true - t.mock.mu.Unlock() - return registered -} - -// Reset changes the expiry time of the timer -func (t *Timer) Reset(d time.Duration) bool { - if t.timer != nil { - return t.timer.Reset(d) - } - - t.mock.mu.Lock() - t.next = t.mock.now.Add(d) - defer t.mock.mu.Unlock() - - registered := !t.stopped - if t.stopped { - t.mock.timers = append(t.mock.timers, (*internalTimer)(t)) - } - - t.stopped = false - return registered -} - -type internalTimer Timer - -func (t *internalTimer) Next() time.Time { return t.next } -func (t *internalTimer) Tick(now time.Time) { - // a gosched() after ticking, to allow any consequences of the - // tick to complete - defer gosched() - - t.mock.mu.Lock() - if t.fn != nil { - // defer function execution until the lock is released, and - defer func() { go t.fn() }() - } else { - t.c <- now - } - t.mock.removeClockTimer((*internalTimer)(t)) - t.stopped = true - t.mock.mu.Unlock() -} - -// Ticker holds a channel that receives "ticks" at regular intervals. -type Ticker struct { - C <-chan time.Time - c chan time.Time - ticker *time.Ticker // realtime impl, if set - next time.Time // next tick time - mock *Mock // mock clock, if set - d time.Duration // time between ticks - stopped bool // True if stopped, false if running -} - -// Stop turns off the ticker. -func (t *Ticker) Stop() { - if t.ticker != nil { - t.ticker.Stop() - } else { - t.mock.mu.Lock() - t.mock.removeClockTimer((*internalTicker)(t)) - t.stopped = true - t.mock.mu.Unlock() - } -} - -// Reset resets the ticker to a new duration. -func (t *Ticker) Reset(dur time.Duration) { - if t.ticker != nil { - t.ticker.Reset(dur) - return - } - - t.mock.mu.Lock() - defer t.mock.mu.Unlock() - - if t.stopped { - t.mock.timers = append(t.mock.timers, (*internalTicker)(t)) - t.stopped = false - } - - t.d = dur - t.next = t.mock.now.Add(dur) -} - -type internalTicker Ticker - -func (t *internalTicker) Next() time.Time { return t.next } -func (t *internalTicker) Tick(now time.Time) { - select { - case t.c <- now: - default: - } - t.mock.mu.Lock() - t.next = now.Add(t.d) - t.mock.mu.Unlock() - gosched() -} - -// Sleep momentarily so that other goroutines can process. -func gosched() { time.Sleep(1 * time.Millisecond) } - -var ( - // type checking - _ Clock = &Mock{} -) diff --git a/vendor/github.com/benbjohnson/clock/context.go b/vendor/github.com/benbjohnson/clock/context.go deleted file mode 100644 index eb67594f2c..0000000000 --- a/vendor/github.com/benbjohnson/clock/context.go +++ /dev/null @@ -1,86 +0,0 @@ -package clock - -import ( - "context" - "fmt" - "sync" - "time" -) - -func (m *Mock) WithTimeout(parent context.Context, timeout time.Duration) (context.Context, context.CancelFunc) { - return m.WithDeadline(parent, m.Now().Add(timeout)) -} - -func (m *Mock) WithDeadline(parent context.Context, deadline time.Time) (context.Context, context.CancelFunc) { - if cur, ok := parent.Deadline(); ok && cur.Before(deadline) { - // The current deadline is already sooner than the new one. - return context.WithCancel(parent) - } - ctx := &timerCtx{clock: m, parent: parent, deadline: deadline, done: make(chan struct{})} - propagateCancel(parent, ctx) - dur := m.Until(deadline) - if dur <= 0 { - ctx.cancel(context.DeadlineExceeded) // deadline has already passed - return ctx, func() {} - } - ctx.Lock() - defer ctx.Unlock() - if ctx.err == nil { - ctx.timer = m.AfterFunc(dur, func() { - ctx.cancel(context.DeadlineExceeded) - }) - } - return ctx, func() { ctx.cancel(context.Canceled) } -} - -// propagateCancel arranges for child to be canceled when parent is. -func propagateCancel(parent context.Context, child *timerCtx) { - if parent.Done() == nil { - return // parent is never canceled - } - go func() { - select { - case <-parent.Done(): - child.cancel(parent.Err()) - case <-child.Done(): - } - }() -} - -type timerCtx struct { - sync.Mutex - - clock Clock - parent context.Context - deadline time.Time - done chan struct{} - - err error - timer *Timer -} - -func (c *timerCtx) cancel(err error) { - c.Lock() - defer c.Unlock() - if c.err != nil { - return // already canceled - } - c.err = err - close(c.done) - if c.timer != nil { - c.timer.Stop() - c.timer = nil - } -} - -func (c *timerCtx) Deadline() (deadline time.Time, ok bool) { return c.deadline, true } - -func (c *timerCtx) Done() <-chan struct{} { return c.done } - -func (c *timerCtx) Err() error { return c.err } - -func (c *timerCtx) Value(key interface{}) interface{} { return c.parent.Value(key) } - -func (c *timerCtx) String() string { - return fmt.Sprintf("clock.WithDeadline(%s [%s])", c.deadline, c.deadline.Sub(c.clock.Now())) -} diff --git a/vendor/github.com/coder/quartz/.gitignore b/vendor/github.com/coder/quartz/.gitignore new file mode 100644 index 0000000000..62c893550a --- /dev/null +++ b/vendor/github.com/coder/quartz/.gitignore @@ -0,0 +1 @@ +.idea/ \ No newline at end of file diff --git a/vendor/github.com/coder/quartz/LICENSE b/vendor/github.com/coder/quartz/LICENSE new file mode 100644 index 0000000000..f7c5d7fee6 --- /dev/null +++ b/vendor/github.com/coder/quartz/LICENSE @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be + protected by copyright and related or neighboring rights ("Copyright and + Related Rights"). Copyright and Related Rights include, but are not + limited to, the following: + +i. the right to reproduce, adapt, distribute, perform, display, +communicate, and translate a Work; +ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or +likeness depicted in a Work; +iv. rights protecting against unfair competition in regards to a Work, +subject to the limitations in paragraph 4(a), below; +v. rights protecting the extraction, dissemination, use and reuse of data +in a Work; +vi. database rights (such as those arising under Directive 96/9/EC of the +European Parliament and of the Council of 11 March 1996 on the legal +protection of databases, and under any national implementation +thereof, including any amended or successor version of such +directive); and +vii. other similar, equivalent or corresponding rights throughout the +world based on applicable law or treaty, and any national +implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention + of, applicable law, Affirmer hereby overtly, fully, permanently, + irrevocably and unconditionally waives, abandons, and surrenders all of + Affirmer's Copyright and Related Rights and associated claims and causes + of action, whether now known or unknown (including existing as well as + future claims and causes of action), in the Work (i) in all territories + worldwide, (ii) for the maximum duration provided by applicable law or + treaty (including future time extensions), (iii) in any current or future + medium and for any number of copies, and (iv) for any purpose whatsoever, + including without limitation commercial, advertising or promotional + purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each + member of the public at large and to the detriment of Affirmer's heirs and + successors, fully intending that such Waiver shall not be subject to + revocation, rescission, cancellation, termination, or any other legal or + equitable action to disrupt the quiet enjoyment of the Work by the public + as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason + be judged legally invalid or ineffective under applicable law, then the + Waiver shall be preserved to the maximum extent permitted taking into + account Affirmer's express Statement of Purpose. In addition, to the + extent the Waiver is so judged Affirmer hereby grants to each affected + person a royalty-free, non transferable, non sublicensable, non exclusive, + irrevocable and unconditional license to exercise Affirmer's Copyright and + Related Rights in the Work (i) in all territories worldwide, (ii) for the + maximum duration provided by applicable law or treaty (including future + time extensions), (iii) in any current or future medium and for any number + of copies, and (iv) for any purpose whatsoever, including without + limitation commercial, advertising or promotional purposes (the + "License"). The License shall be deemed effective as of the date CC0 was + applied by Affirmer to the Work. Should any part of the License for any + reason be judged legally invalid or ineffective under applicable law, such + partial invalidity or ineffectiveness shall not invalidate the remainder + of the License, and in such case Affirmer hereby affirms that he or she + will not (i) exercise any of his or her remaining Copyright and Related + Rights in the Work or (ii) assert any associated claims and causes of + action with respect to the Work, in either case contrary to Affirmer's + express Statement of Purpose. + +4. Limitations and Disclaimers. + +a. No trademark or patent rights held by Affirmer are waived, abandoned, +surrendered, licensed or otherwise affected by this document. +b. Affirmer offers the Work as-is and makes no representations or +warranties of any kind concerning the Work, express, implied, +statutory or otherwise, including without limitation warranties of +title, merchantability, fitness for a particular purpose, non +infringement, or the absence of latent or other defects, accuracy, or +the present or absence of errors, whether or not discoverable, all to +the greatest extent permissible under applicable law. +c. Affirmer disclaims responsibility for clearing rights of other persons +that may apply to the Work or any use thereof, including without +limitation any person's Copyright and Related Rights in the Work. +Further, Affirmer disclaims responsibility for obtaining any necessary +consents, permissions or other rights required for any use of the +Work. +d. Affirmer understands and acknowledges that Creative Commons is not a +party to this document and has no duty or obligation with respect to +this CC0 or use of the Work. \ No newline at end of file diff --git a/vendor/github.com/coder/quartz/README.md b/vendor/github.com/coder/quartz/README.md new file mode 100644 index 0000000000..f0703c4d74 --- /dev/null +++ b/vendor/github.com/coder/quartz/README.md @@ -0,0 +1,632 @@ +# Quartz + +A Go time testing library for writing deterministic unit tests + +Our high level goal is to write unit tests that + +1. execute quickly +2. don't flake +3. are straightforward to write and understand + +For tests to execute quickly without flakes, we want to focus on _determinism_: the test should run +the same each time, and it should be easy to force the system into a known state (no races) before +executing test assertions. `time.Sleep`, `runtime.Gosched()`, and +polling/[Eventually](https://pkg.go.dev/github.com/stretchr/testify/assert#Eventually) are all +symptoms of an inability to do this easily. + +## Usage + +### `Clock` interface + +In your application code, maintain a reference to a `quartz.Clock` instance to start timers and +tickers, instead of the bare `time` standard library. + +```go +import "github.com/coder/quartz" + +type Component struct { + ... + + // for testing + clock quartz.Clock +} +``` + +Whenever you would call into `time` to start a timer or ticker, call `Component`'s `clock` instead. + +In production, set this clock to `quartz.NewReal()` to create a clock that just transparently passes +through to the standard `time` library. + +### Mocking + +In your tests, you can use a `*Mock` to control the tickers and timers your code under test gets. + +```go +import ( + "testing" + "github.com/coder/quartz" +) + +func TestComponent(t *testing.T) { + mClock := quartz.NewMock(t) + comp := &Component{ + ... + clock: mClock, + } +} +``` + +The `*Mock` clock starts at Jan 1, 2024, 00:00 UTC by default, but you can set any start time you'd like prior to your test. + +```go +mClock := quartz.NewMock(t) +mClock.Set(time.Date(2021, 6, 18, 12, 0, 0, 0, time.UTC)) // June 18, 2021 @ 12pm UTC +``` + +#### Advancing the clock + +Once you begin setting timers or tickers, you cannot change the time backward, only advance it +forward. You may continue to use `Set()`, but it is often easier and clearer to use `Advance()`. + +For example, with a timer: + +```go +fired := false + +tmr := mClock.AfterFunc(time.Second, func() { + fired = true +}) +mClock.Advance(time.Second) +``` + +When you call `Advance()` it immediately moves the clock forward the given amount, and triggers any +tickers or timers that are scheduled to happen at that time. Any triggered events happen on separate +goroutines, so _do not_ immediately assert the results: + +```go +fired := false + +tmr := mClock.AfterFunc(time.Second, func() { + fired = true +}) +mClock.Advance(time.Second) + +// RACE CONDITION, DO NOT DO THIS! +if !fired { + t.Fatal("didn't fire") +} +``` + +`Advance()` (and `Set()` for that matter) return an `AdvanceWaiter` object you can use to wait for +all triggered events to complete. + +```go +fired := false +// set a test timeout so we don't wait the default `go test` timeout for a failure +ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + +tmr := mClock.AfterFunc(time.Second, func() { + fired = true +}) + +w := mClock.Advance(time.Second) +err := w.Wait(ctx) +if err != nil { + t.Fatal("AfterFunc f never completed") +} +if !fired { + t.Fatal("didn't fire") +} +``` + +The construction of waiting for the triggered events and failing the test if they don't complete is +very common, so there is a shorthand: + +```go +w := mClock.Advance(time.Second) +err := w.Wait(ctx) +if err != nil { + t.Fatal("AfterFunc f never completed") +} +``` + +is equivalent to: + +```go +w := mClock.Advance(time.Second) +w.MustWait(ctx) +``` + +or even more briefly: + +```go +mClock.Advance(time.Second).MustWait(ctx) +``` + +### Advance only to the next event + +One important restriction on advancing the clock is that you may only advance forward to the next +timer or ticker event and no further. The following will result in a test failure: + +```go +func TestAdvanceTooFar(t *testing.T) { + ctx, cancel := context.WithTimeout(10*time.Second) + defer cancel() + mClock := quartz.NewMock(t) + var firedAt time.Time + mClock.AfterFunc(time.Second, func() { + firedAt := mClock.Now() + }) + mClock.Advance(2*time.Second).MustWait(ctx) +} +``` + +This is a deliberate design decision to allow `Advance()` to immediately and synchronously move the +clock forward (even without calling `Wait()` on returned waiter). This helps meet Quartz's design +goals of writing deterministic and easy to understand unit tests. It also allows the clock to be +advanced, deterministically _during_ the execution of a tick or timer function, as explained in the +next sections on Traps. + +Advancing multiple events can be accomplished via looping. E.g. if you have a 1-second ticker + +```go +for i := 0; i < 10; i++ { + mClock.Advance(time.Second).MustWait(ctx) +} +``` + +will advance 10 ticks. + +If you don't know or don't want to compute the time to the next event, you can use `AdvanceNext()`. + +```go +d, w := mClock.AdvanceNext() +w.MustWait(ctx) +// d contains the duration we advanced +``` + +`d, ok := Peek()` returns the duration until the next event, if any (`ok` is `true`). You can use +this to advance a specific time, regardless of the tickers and timer events: + +```go +desired := time.Minute // time to advance +for desired > 0 { + p, ok := mClock.Peek() + if !ok || p > desired { + mClock.Advance(desired).MustWait(ctx) + break + } + mClock.Advance(p).MustWait(ctx) + desired -= p +} +``` + +### Traps + +A trap allows you to match specific calls into the library while mocking, block their return, +inspect their arguments, then release them to allow them to return. They help you write +deterministic unit tests even when the code under test executes asynchronously from the test. + +You set your traps prior to executing code under test, and then wait for them to be triggered. + +```go +func TestTrap(t *testing.T) { + ctx, cancel := context.WithTimeout(10*time.Second) + defer cancel() + mClock := quartz.NewMock(t) + trap := mClock.Trap().AfterFunc() + defer trap.Close() // stop trapping AfterFunc calls + + count := 0 + go mClock.AfterFunc(time.Hour, func(){ + count++ + }) + call := trap.MustWait(ctx) + call.Release() + if call.Duration != time.Hour { + t.Fatal("wrong duration") + } + + // Now that the async call to AfterFunc has occurred, we can advance the clock to trigger it + mClock.Advance(call.Duration).MustWait(ctx) + if count != 1 { + t.Fatal("wrong count") + } +} +``` + +In this test, the trap serves 2 purposes. Firstly, it allows us to capture and assert the duration +passed to the `AfterFunc` call. Secondly, it prevents a race between setting the timer and advancing +it. Since these things happen on different goroutines, if `Advance()` completes before +`AfterFunc()` is called, then the timer never pops in this test. + +Any untrapped calls immediately complete using the current time, and calling `Close()` on a trap +causes the mock clock to stop trapping those calls. + +You may also `Advance()` the clock between trapping a call and releasing it. The call uses the +current (mocked) time at the moment it is released. + +```go +func TestTrap2(t *testing.T) { + ctx, cancel := context.WithTimeout(10*time.Second) + defer cancel() + mClock := quartz.NewMock(t) + trap := mClock.Trap().Now() + defer trap.Close() // stop trapping AfterFunc calls + + var logs []string + done := make(chan struct{}) + go func(clk quartz.Clock){ + defer close(done) + start := clk.Now() + phase1() + p1end := clk.Now() + logs = append(fmt.Sprintf("Phase 1 took %s", p1end.Sub(start).String())) + phase2() + p2end := clk.Now() + logs = append(fmt.Sprintf("Phase 2 took %s", p2end.Sub(p1end).String())) + }(mClock) + + // start + trap.MustWait(ctx).Release() + // phase 1 + call := trap.MustWait(ctx) + mClock.Advance(3*time.Second).MustWait(ctx) + call.Release() + // phase 2 + call = trap.MustWait(ctx) + mClock.Advance(5*time.Second).MustWait(ctx) + call.Release() + + <-done + // Now logs contains []string{"Phase 1 took 3s", "Phase 2 took 5s"} +} +``` + +### Tags + +When multiple goroutines in the code under test call into the Clock, you can use `tags` to +distinguish them in your traps. + +```go +trap := mClock.Trap.Now("foo") // traps any calls that contain "foo" +defer trap.Close() + +foo := make(chan time.Time) +go func(){ + foo <- mClock.Now("foo", "bar") +}() +baz := make(chan time.Time) +go func(){ + baz <- mClock.Now("baz") +}() +call := trap.MustWait(ctx) +mClock.Advance(time.Second).MustWait(ctx) +call.Release() +// call.Tags contains []string{"foo", "bar"} + +gotFoo := <-foo // 1s after start +gotBaz := <-baz // ?? never trapped, so races with Advance() +``` + +Tags appear as an optional suffix on all `Clock` methods (type `...string`) and are ignored entirely +by the real clock. They also appear on all methods on returned timers and tickers. + +## Recommended Patterns + +### Options + +We use the Option pattern to inject the mock clock for testing, keeping the call signature in +production clean. The option pattern is compatible with other optional fields as well. + +```go +type Option func(*Thing) + +// WithTestClock is used in tests to inject a mock Clock +func WithTestClock(clk quartz.Clock) Option { + return func(t *Thing) { + t.clock = clk + } +} + +func NewThing(, opts ...Option) *Thing { + t := &Thing{ + ... + clock: quartz.NewReal() + } + for _, o := range opts { + o(t) + } + return t +} +``` + +In tests, this becomes + +```go +func TestThing(t *testing.T) { + mClock := quartz.NewMock(t) + thing := NewThing(, WithTestClock(mClock)) + ... +} +``` + +### Tagging convention + +Tag your `Clock` method calls as: + +```go +func (c *Component) Method() { + now := c.clock.Now("Component", "Method") +} +``` + +or + +```go +func (c *Component) Method() { + start := c.clock.Now("Component", "Method", "start") + ... + end := c.clock.Now("Component", "Method", "end") +} +``` + +This makes it much less likely that code changes that introduce new components or methods will spoil +existing unit tests. + +## Why another time testing library? + +Writing good unit tests for components and functions that use the `time` package is difficult, even +though several open source libraries exist. In building Quartz, we took some inspiration from + +- [github.com/benbjohnson/clock](https://github.com/benbjohnson/clock) +- Tailscale's [tstest.Clock](https://github.com/coder/tailscale/blob/main/tstest/clock.go) +- [github.com/aspenmesh/tock](https://github.com/aspenmesh/tock) + +Quartz shares the high level design of a `Clock` interface that closely resembles the functions in +the `time` standard library, and a "real" clock passes thru to the standard library in production, +while a mock clock gives precise control in testing. + +As mentioned in our introduction, our high level goal is to write unit tests that + +1. execute quickly +2. don't flake +3. are straightforward to write and understand + +For several reasons, this is a tall order when it comes to code that depends on time, and we found +the existing libraries insufficient for our goals. + +### Preventing test flakes + +The following example comes from the README from benbjohnson/clock: + +```go +mock := clock.NewMock() +count := 0 + +// Kick off a timer to increment every 1 mock second. +go func() { + ticker := mock.Ticker(1 * time.Second) + for { + <-ticker.C + count++ + } +}() +runtime.Gosched() + +// Move the clock forward 10 seconds. +mock.Add(10 * time.Second) + +// This prints 10. +fmt.Println(count) +``` + +The first race condition is fairly obvious: moving the clock forward 10 seconds may generate 10 +ticks on the `ticker.C` channel, but there is no guarantee that `count++` executes before +`fmt.Println(count)`. + +The second race condition is more subtle, but `runtime.Gosched()` is the tell. Since the ticker +is started on a separate goroutine, there is no guarantee that `mock.Ticker()` executes before +`mock.Add()`. `runtime.Gosched()` is an attempt to get this to happen, but it makes no hard +promises. On a busy system, especially when running tests in parallel, this can flake, advance the +time 10 seconds first, then start the ticker and never generate a tick. + +Let's talk about how Quartz tackles these problems. + +In our experience, an extremely common use case is creating a ticker then doing a 2-arm `select` +with ticks in one and context expiring in another, i.e. + +```go +t := time.NewTicker(duration) +for { + select { + case <-ctx.Done(): + return ctx.Err() + case <-t.C: + err := do() + if err != nil { + return err + } + } +} +``` + +In Quartz, we refactor this to be more compact and testing friendly: + +```go +t := clock.TickerFunc(ctx, duration, do) +return t.Wait() +``` + +This affords the mock `Clock` the ability to explicitly know when processing of a tick is finished +because it's wrapped in the function passed to `TickerFunc` (`do()` in this example). + +In Quartz, when you advance the clock, you are returned an object you can `Wait()` on to ensure all +ticks and timers triggered are finished. This solves the first race condition in the example. + +(As an aside, we still support a traditional standard library-style `Ticker`. You may find it useful +if you want to keep your code as close as possible to the standard library, or if you need to use +the channel in a larger `select` block. In that case, you'll have to find some other mechanism to +sync tick processing to your test code.) + +To prevent race conditions related to the starting of the ticker, Quartz allows you to set "traps" +for calls that access the clock. + +```go +func TestTicker(t *testing.T) { + mClock := quartz.NewMock(t) + trap := mClock.Trap().TickerFunc() + defer trap.Close() // stop trapping at end + go runMyTicker(mClock) // async calls TickerFunc() + call := trap.Wait(context.Background()) // waits for a call and blocks its return + call.Release() // allow the TickerFunc() call to return + // optionally check the duration using call.Duration + // Move the clock forward 1 tick + mClock.Advance(time.Second).MustWait(context.Background()) + // assert results of the tick +} +``` + +Trapping and then releasing the call to `TickerFunc()` ensures the ticker is started at a +deterministic time, so our calls to `Advance()` will have a predictable effect. + +Take a look at `TestExampleTickerFunc` in `example_test.go` for a complete worked example. + +### Complex time dependence + +Another difficult issue to handle when unit testing is when some code under test makes multiple +calls that depend on the time, and you want to simulate some time passing between them. + +A very basic example is measuring how long something took: + +```go +var measurement time.Duration +go func(clock quartz.Clock) { + start := clock.Now() + doSomething() + measurement = clock.Since(start) +}(mClock) + +// how to get measurement to be, say, 5 seconds? +``` + +The two calls into the clock happen asynchronously, so we need to be able to advance the clock after +the first call to `Now()` but before the call to `Since()`. Doing this with the libraries we +mentioned above means that you have to be able to mock out or otherwise block the completion of +`doSomething()`. + +But, with the trap functionality we mentioned in the previous section, you can deterministically +control the time each call sees. + +```go +trap := mClock.Trap().Since() +var measurement time.Duration +go func(clock quartz.Clock) { + start := clock.Now() + doSomething() + measurement = clock.Since(start) +}(mClock) + +c := trap.Wait(ctx) +mClock.Advance(5*time.Second) +c.Release() +``` + +We wait until we trap the `clock.Since()` call, which implies that `clock.Now()` has completed, then +advance the mock clock 5 seconds. Finally, we release the `clock.Since()` call. Any changes to the +clock that happen _before_ we release the call will be included in the time used for the +`clock.Since()` call. + +As a more involved example, consider an inactivity timeout: we want something to happen if there is +no activity recorded for some period, say 10 minutes in the following example: + +```go +type InactivityTimer struct { + mu sync.Mutex + activity time.Time + clock quartz.Clock +} + +func (i *InactivityTimer) Start() { + i.mu.Lock() + defer i.mu.Unlock() + next := i.clock.Until(i.activity.Add(10*time.Minute)) + t := i.clock.AfterFunc(next, func() { + i.mu.Lock() + defer i.mu.Unlock() + next := i.clock.Until(i.activity.Add(10*time.Minute)) + if next == 0 { + i.timeoutLocked() + return + } + t.Reset(next) + }) +} +``` + +The actual contents of `timeoutLocked()` doesn't matter for this example, and assume there are other +functions that record the latest `activity`. + +We found that some time testing libraries hold a lock on the mock clock while calling the function +passed to `AfterFunc`, resulting in a deadlock if you made clock calls from within. + +Others allow this sort of thing, but don't have the flexibility to test edge cases. There is a +subtle bug in our `Start()` function. The timer may pop a little late, and/or some measurable real +time may elapse before `Until()` gets called inside the `AfterFunc`. If there hasn't been activity, +`next` might be negative. + +To test this in Quartz, we'll use a trap. We only want to trap the inner `Until()` call, not the +initial one, so to make testing easier we can "tag" the call we want. Like this: + +```go +func (i *InactivityTimer) Start() { + i.mu.Lock() + defer i.mu.Unlock() + next := i.clock.Until(i.activity.Add(10*time.Minute)) + t := i.clock.AfterFunc(next, func() { + i.mu.Lock() + defer i.mu.Unlock() + next := i.clock.Until(i.activity.Add(10*time.Minute), "inner") + if next == 0 { + i.timeoutLocked() + return + } + t.Reset(next) + }) +} +``` + +All Quartz `Clock` functions, and functions on returned timers and tickers support zero or more +string tags that allow traps to match on them. + +```go +func TestInactivityTimer_Late(t *testing.T) { + // set a timeout on the test itself, so that if Wait functions get blocked, we don't have to + // wait for the default test timeout of 10 minutes. + ctx, cancel := context.WithTimeout(10*time.Second) + defer cancel() + mClock := quartz.NewMock(t) + trap := mClock.Trap.Until("inner") + defer trap.Close() + + it := &InactivityTimer{ + activity: mClock.Now(), + clock: mClock, + } + it.Start() + + // Trigger the AfterFunc + w := mClock.Advance(10*time.Minute) + c := trap.Wait(ctx) + // Advance the clock a few ms to simulate a busy system + mClock.Advance(3*time.Millisecond) + c.Release() // Until() returns + w.MustWait(ctx) // Wait for the AfterFunc to wrap up + + // Assert that the timeoutLocked() function was called +} +``` + +This test case will fail with our bugged implementation, since the triggered AfterFunc won't call +`timeoutLocked()` and instead will reset the timer with a negative number. The fix is easy, use +`next <= 0` as the comparison. diff --git a/vendor/github.com/coder/quartz/clock.go b/vendor/github.com/coder/quartz/clock.go new file mode 100644 index 0000000000..729edfa562 --- /dev/null +++ b/vendor/github.com/coder/quartz/clock.go @@ -0,0 +1,43 @@ +// Package quartz is a library for testing time related code. It exports an interface Clock that +// mimics the standard library time package functions. In production, an implementation that calls +// thru to the standard library is used. In testing, a Mock clock is used to precisely control and +// intercept time functions. +package quartz + +import ( + "context" + "time" +) + +type Clock interface { + // NewTicker returns a new Ticker containing a channel that will send the current time on the + // channel after each tick. The period of the ticks is specified by the duration argument. The + // ticker will adjust the time interval or drop ticks to make up for slow receivers. The + // duration d must be greater than zero; if not, NewTicker will panic. Stop the ticker to + // release associated resources. + NewTicker(d time.Duration, tags ...string) *Ticker + // TickerFunc is a convenience function that calls f on the interval d until either the given + // context expires or f returns an error. Callers may call Wait() on the returned Waiter to + // wait until this happens and obtain the error. The duration d must be greater than zero; if + // not, TickerFunc will panic. + TickerFunc(ctx context.Context, d time.Duration, f func() error, tags ...string) Waiter + // NewTimer creates a new Timer that will send the current time on its channel after at least + // duration d. + NewTimer(d time.Duration, tags ...string) *Timer + // AfterFunc waits for the duration to elapse and then calls f in its own goroutine. It returns + // a Timer that can be used to cancel the call using its Stop method. The returned Timer's C + // field is not used and will be nil. + AfterFunc(d time.Duration, f func(), tags ...string) *Timer + + // Now returns the current local time. + Now(tags ...string) time.Time + // Since returns the time elapsed since t. It is shorthand for Clock.Now().Sub(t). + Since(t time.Time, tags ...string) time.Duration + // Until returns the duration until t. It is shorthand for t.Sub(Clock.Now()). + Until(t time.Time, tags ...string) time.Duration +} + +// Waiter can be waited on for an error. +type Waiter interface { + Wait(tags ...string) error +} diff --git a/vendor/github.com/coder/quartz/mock.go b/vendor/github.com/coder/quartz/mock.go new file mode 100644 index 0000000000..cc8e064c21 --- /dev/null +++ b/vendor/github.com/coder/quartz/mock.go @@ -0,0 +1,661 @@ +package quartz + +import ( + "context" + "errors" + "fmt" + "slices" + "sync" + "testing" + "time" +) + +// Mock is the testing implementation of Clock. It tracks a time that monotonically increases +// during a test, triggering any timers or tickers automatically. +type Mock struct { + tb testing.TB + mu sync.Mutex + + // cur is the current time + cur time.Time + + all []event + nextTime time.Time + nextEvents []event + traps []*Trap +} + +type event interface { + next() time.Time + fire(t time.Time) +} + +func (m *Mock) TickerFunc(ctx context.Context, d time.Duration, f func() error, tags ...string) Waiter { + if d <= 0 { + panic("TickerFunc called with negative or zero duration") + } + m.mu.Lock() + defer m.mu.Unlock() + c := newCall(clockFunctionTickerFunc, tags, withDuration(d)) + m.matchCallLocked(c) + defer close(c.complete) + t := &mockTickerFunc{ + ctx: ctx, + d: d, + f: f, + nxt: m.cur.Add(d), + mock: m, + cond: sync.NewCond(&m.mu), + } + m.all = append(m.all, t) + m.recomputeNextLocked() + go t.waitForCtx() + return t +} + +func (m *Mock) NewTicker(d time.Duration, tags ...string) *Ticker { + if d <= 0 { + panic("NewTicker called with negative or zero duration") + } + m.mu.Lock() + defer m.mu.Unlock() + c := newCall(clockFunctionNewTicker, tags, withDuration(d)) + m.matchCallLocked(c) + defer close(c.complete) + // 1 element buffer follows standard library implementation + ticks := make(chan time.Time, 1) + t := &Ticker{ + C: ticks, + c: ticks, + d: d, + nxt: m.cur.Add(d), + mock: m, + } + m.addEventLocked(t) + return t +} + +func (m *Mock) NewTimer(d time.Duration, tags ...string) *Timer { + m.mu.Lock() + defer m.mu.Unlock() + c := newCall(clockFunctionNewTimer, tags, withDuration(d)) + defer close(c.complete) + m.matchCallLocked(c) + ch := make(chan time.Time, 1) + t := &Timer{ + C: ch, + c: ch, + nxt: m.cur.Add(d), + mock: m, + } + if d <= 0 { + // zero or negative duration timer means we should immediately fire + // it, rather than add it. + go t.fire(t.mock.cur) + return t + } + m.addEventLocked(t) + return t +} + +func (m *Mock) AfterFunc(d time.Duration, f func(), tags ...string) *Timer { + m.mu.Lock() + defer m.mu.Unlock() + c := newCall(clockFunctionAfterFunc, tags, withDuration(d)) + defer close(c.complete) + m.matchCallLocked(c) + t := &Timer{ + nxt: m.cur.Add(d), + fn: f, + mock: m, + } + if d <= 0 { + // zero or negative duration timer means we should immediately fire + // it, rather than add it. + go t.fire(t.mock.cur) + return t + } + m.addEventLocked(t) + return t +} + +func (m *Mock) Now(tags ...string) time.Time { + m.mu.Lock() + defer m.mu.Unlock() + c := newCall(clockFunctionNow, tags) + defer close(c.complete) + m.matchCallLocked(c) + return m.cur +} + +func (m *Mock) Since(t time.Time, tags ...string) time.Duration { + m.mu.Lock() + defer m.mu.Unlock() + c := newCall(clockFunctionSince, tags, withTime(t)) + defer close(c.complete) + m.matchCallLocked(c) + return m.cur.Sub(t) +} + +func (m *Mock) Until(t time.Time, tags ...string) time.Duration { + m.mu.Lock() + defer m.mu.Unlock() + c := newCall(clockFunctionUntil, tags, withTime(t)) + defer close(c.complete) + m.matchCallLocked(c) + return t.Sub(m.cur) +} + +func (m *Mock) addEventLocked(e event) { + m.all = append(m.all, e) + m.recomputeNextLocked() +} + +func (m *Mock) recomputeNextLocked() { + var best time.Time + var events []event + for _, e := range m.all { + if best.IsZero() || e.next().Before(best) { + best = e.next() + events = []event{e} + continue + } + if e.next().Equal(best) { + events = append(events, e) + continue + } + } + m.nextTime = best + m.nextEvents = events +} + +func (m *Mock) removeTimer(t *Timer) { + m.mu.Lock() + defer m.mu.Unlock() + m.removeTimerLocked(t) +} + +func (m *Mock) removeTimerLocked(t *Timer) { + t.stopped = true + m.removeEventLocked(t) +} + +func (m *Mock) removeEventLocked(e event) { + defer m.recomputeNextLocked() + for i := range m.all { + if m.all[i] == e { + m.all = append(m.all[:i], m.all[i+1:]...) + return + } + } +} + +func (m *Mock) matchCallLocked(c *Call) { + var traps []*Trap + for _, t := range m.traps { + if t.matches(c) { + traps = append(traps, t) + } + } + if len(traps) == 0 { + return + } + c.releases.Add(len(traps)) + m.mu.Unlock() + for _, t := range traps { + go t.catch(c) + } + c.releases.Wait() + m.mu.Lock() +} + +// AdvanceWaiter is returned from Advance and Set calls and allows you to wait for ticks and timers +// to complete. In the case of functions passed to AfterFunc or TickerFunc, it waits for the +// functions to return. For other ticks & timers, it just waits for the tick to be delivered to +// the channel. +// +// If multiple timers or tickers trigger simultaneously, they are all run on separate +// go routines. +type AdvanceWaiter struct { + tb testing.TB + ch chan struct{} +} + +// Wait for all timers and ticks to complete, or until context expires. +func (w AdvanceWaiter) Wait(ctx context.Context) error { + select { + case <-w.ch: + return nil + case <-ctx.Done(): + return ctx.Err() + } +} + +// MustWait waits for all timers and ticks to complete, and fails the test immediately if the +// context completes first. MustWait must be called from the goroutine running the test or +// benchmark, similar to `t.FailNow()`. +func (w AdvanceWaiter) MustWait(ctx context.Context) { + w.tb.Helper() + select { + case <-w.ch: + return + case <-ctx.Done(): + w.tb.Fatalf("context expired while waiting for clock to advance: %s", ctx.Err()) + } +} + +// Done returns a channel that is closed when all timers and ticks complete. +func (w AdvanceWaiter) Done() <-chan struct{} { + return w.ch +} + +// Advance moves the clock forward by d, triggering any timers or tickers. The returned value can +// be used to wait for all timers and ticks to complete. Advance sets the clock forward before +// returning, and can only advance up to the next timer or tick event. It will fail the test if you +// attempt to advance beyond. +// +// If you need to advance exactly to the next event, and don't know or don't wish to calculate it, +// consider AdvanceNext(). +func (m *Mock) Advance(d time.Duration) AdvanceWaiter { + m.tb.Helper() + w := AdvanceWaiter{tb: m.tb, ch: make(chan struct{})} + m.mu.Lock() + fin := m.cur.Add(d) + // nextTime.IsZero implies no events scheduled. + if m.nextTime.IsZero() || fin.Before(m.nextTime) { + m.cur = fin + m.mu.Unlock() + close(w.ch) + return w + } + if fin.After(m.nextTime) { + m.tb.Errorf(fmt.Sprintf("cannot advance %s which is beyond next timer/ticker event in %s", + d.String(), m.nextTime.Sub(m.cur))) + m.mu.Unlock() + close(w.ch) + return w + } + + m.cur = m.nextTime + go m.advanceLocked(w) + return w +} + +func (m *Mock) advanceLocked(w AdvanceWaiter) { + defer close(w.ch) + wg := sync.WaitGroup{} + for i := range m.nextEvents { + e := m.nextEvents[i] + t := m.cur + wg.Add(1) + go func() { + e.fire(t) + wg.Done() + }() + } + // release the lock and let the events resolve. This allows them to call back into the + // Mock to query the time or set new timers. Each event should remove or reschedule + // itself from nextEvents. + m.mu.Unlock() + wg.Wait() +} + +// Set the time to t. If the time is after the current mocked time, then this is equivalent to +// Advance() with the difference. You may only Set the time earlier than the current time before +// starting tickers and timers (e.g. at the start of your test case). +func (m *Mock) Set(t time.Time) AdvanceWaiter { + m.tb.Helper() + w := AdvanceWaiter{tb: m.tb, ch: make(chan struct{})} + m.mu.Lock() + if t.Before(m.cur) { + defer close(w.ch) + defer m.mu.Unlock() + // past + if !m.nextTime.IsZero() { + m.tb.Error("Set mock clock to the past after timers/tickers started") + } + m.cur = t + return w + } + // future + // nextTime.IsZero implies no events scheduled. + if m.nextTime.IsZero() || t.Before(m.nextTime) { + defer close(w.ch) + defer m.mu.Unlock() + m.cur = t + return w + } + if t.After(m.nextTime) { + defer close(w.ch) + defer m.mu.Unlock() + m.tb.Errorf("cannot Set time to %s which is beyond next timer/ticker event at %s", + t.String(), m.nextTime) + return w + } + + m.cur = m.nextTime + go m.advanceLocked(w) + return w +} + +// AdvanceNext advances the clock to the next timer or tick event. It fails the test if there are +// none scheduled. It returns the duration the clock was advanced and a waiter that can be used to +// wait for the timer/tick event(s) to finish. +func (m *Mock) AdvanceNext() (time.Duration, AdvanceWaiter) { + m.mu.Lock() + m.tb.Helper() + w := AdvanceWaiter{tb: m.tb, ch: make(chan struct{})} + if m.nextTime.IsZero() { + defer close(w.ch) + defer m.mu.Unlock() + m.tb.Error("cannot AdvanceNext because there are no timers or tickers running") + } + d := m.nextTime.Sub(m.cur) + m.cur = m.nextTime + go m.advanceLocked(w) + return d, w +} + +// Peek returns the duration until the next ticker or timer event and the value +// true, or, if there are no running tickers or timers, it returns zero and +// false. +func (m *Mock) Peek() (d time.Duration, ok bool) { + m.mu.Lock() + defer m.mu.Unlock() + if m.nextTime.IsZero() { + return 0, false + } + return m.nextTime.Sub(m.cur), true +} + +// Trapper allows the creation of Traps +type Trapper struct { + // mock is the underlying Mock. This is a thin wrapper around Mock so that + // we can have our interface look like mClock.Trap().NewTimer("foo") + mock *Mock +} + +func (t Trapper) NewTimer(tags ...string) *Trap { + return t.mock.newTrap(clockFunctionNewTimer, tags) +} + +func (t Trapper) AfterFunc(tags ...string) *Trap { + return t.mock.newTrap(clockFunctionAfterFunc, tags) +} + +func (t Trapper) TimerStop(tags ...string) *Trap { + return t.mock.newTrap(clockFunctionTimerStop, tags) +} + +func (t Trapper) TimerReset(tags ...string) *Trap { + return t.mock.newTrap(clockFunctionTimerReset, tags) +} + +func (t Trapper) TickerFunc(tags ...string) *Trap { + return t.mock.newTrap(clockFunctionTickerFunc, tags) +} + +func (t Trapper) TickerFuncWait(tags ...string) *Trap { + return t.mock.newTrap(clockFunctionTickerFuncWait, tags) +} + +func (t Trapper) NewTicker(tags ...string) *Trap { + return t.mock.newTrap(clockFunctionNewTicker, tags) +} + +func (t Trapper) TickerStop(tags ...string) *Trap { + return t.mock.newTrap(clockFunctionTickerStop, tags) +} + +func (t Trapper) TickerReset(tags ...string) *Trap { + return t.mock.newTrap(clockFunctionTickerReset, tags) +} + +func (t Trapper) Now(tags ...string) *Trap { + return t.mock.newTrap(clockFunctionNow, tags) +} + +func (t Trapper) Since(tags ...string) *Trap { + return t.mock.newTrap(clockFunctionSince, tags) +} + +func (t Trapper) Until(tags ...string) *Trap { + return t.mock.newTrap(clockFunctionUntil, tags) +} + +func (m *Mock) Trap() Trapper { + return Trapper{m} +} + +func (m *Mock) newTrap(fn clockFunction, tags []string) *Trap { + m.mu.Lock() + defer m.mu.Unlock() + tr := &Trap{ + fn: fn, + tags: tags, + mock: m, + calls: make(chan *Call), + done: make(chan struct{}), + } + m.traps = append(m.traps, tr) + return tr +} + +// NewMock creates a new Mock with the time set to midnight UTC on Jan 1, 2024. +// You may re-set the time earlier than this, but only before timers or tickers +// are created. +func NewMock(tb testing.TB) *Mock { + cur, err := time.Parse(time.RFC3339, "2024-01-01T00:00:00Z") + if err != nil { + panic(err) + } + return &Mock{ + tb: tb, + cur: cur, + } +} + +var _ Clock = &Mock{} + +type mockTickerFunc struct { + ctx context.Context + d time.Duration + f func() error + nxt time.Time + mock *Mock + + // cond is a condition Locked on the main Mock.mu + cond *sync.Cond + // inProgress is true when we are actively calling f + inProgress bool + // done is true when the ticker exits + done bool + // err holds the error when the ticker exits + err error +} + +func (m *mockTickerFunc) next() time.Time { + return m.nxt +} + +func (m *mockTickerFunc) fire(_ time.Time) { + m.mock.mu.Lock() + if m.done { + m.mock.mu.Unlock() + return + } + m.nxt = m.nxt.Add(m.d) + m.mock.recomputeNextLocked() + // we need this check to happen after we've computed the next tick, + // otherwise it will be immediately rescheduled. + if m.inProgress { + m.mock.mu.Unlock() + return + } + + m.inProgress = true + m.mock.mu.Unlock() + err := m.f() + m.mock.mu.Lock() + defer m.mock.mu.Unlock() + m.inProgress = false + m.cond.Broadcast() // wake up anything waiting for f to finish + if err != nil { + m.exitLocked(err) + } +} + +func (m *mockTickerFunc) exitLocked(err error) { + if m.done { + return + } + m.done = true + m.err = err + m.mock.removeEventLocked(m) + m.cond.Broadcast() +} + +func (m *mockTickerFunc) waitForCtx() { + <-m.ctx.Done() + m.mock.mu.Lock() + defer m.mock.mu.Unlock() + for m.inProgress { + m.cond.Wait() + } + m.exitLocked(m.ctx.Err()) +} + +func (m *mockTickerFunc) Wait(tags ...string) error { + m.mock.mu.Lock() + defer m.mock.mu.Unlock() + c := newCall(clockFunctionTickerFuncWait, tags) + m.mock.matchCallLocked(c) + defer close(c.complete) + for !m.done { + m.cond.Wait() + } + return m.err +} + +var _ Waiter = &mockTickerFunc{} + +type clockFunction int + +const ( + clockFunctionNewTimer clockFunction = iota + clockFunctionAfterFunc + clockFunctionTimerStop + clockFunctionTimerReset + clockFunctionTickerFunc + clockFunctionTickerFuncWait + clockFunctionNewTicker + clockFunctionTickerReset + clockFunctionTickerStop + clockFunctionNow + clockFunctionSince + clockFunctionUntil +) + +type callArg func(c *Call) + +type Call struct { + Time time.Time + Duration time.Duration + Tags []string + + fn clockFunction + releases sync.WaitGroup + complete chan struct{} +} + +func (c *Call) Release() { + c.releases.Done() + <-c.complete +} + +func withTime(t time.Time) callArg { + return func(c *Call) { + c.Time = t + } +} + +func withDuration(d time.Duration) callArg { + return func(c *Call) { + c.Duration = d + } +} + +func newCall(fn clockFunction, tags []string, args ...callArg) *Call { + c := &Call{ + fn: fn, + Tags: tags, + complete: make(chan struct{}), + } + for _, a := range args { + a(c) + } + return c +} + +type Trap struct { + fn clockFunction + tags []string + mock *Mock + calls chan *Call + done chan struct{} +} + +func (t *Trap) catch(c *Call) { + select { + case t.calls <- c: + case <-t.done: + c.Release() + } +} + +func (t *Trap) matches(c *Call) bool { + if t.fn != c.fn { + return false + } + for _, tag := range t.tags { + if !slices.Contains(c.Tags, tag) { + return false + } + } + return true +} + +func (t *Trap) Close() { + t.mock.mu.Lock() + defer t.mock.mu.Unlock() + for i, tr := range t.mock.traps { + if t == tr { + t.mock.traps = append(t.mock.traps[:i], t.mock.traps[i+1:]...) + } + } + close(t.done) +} + +var ErrTrapClosed = errors.New("trap closed") + +func (t *Trap) Wait(ctx context.Context) (*Call, error) { + select { + case <-ctx.Done(): + return nil, ctx.Err() + case <-t.done: + return nil, ErrTrapClosed + case c := <-t.calls: + return c, nil + } +} + +// MustWait calls Wait() and then if there is an error, immediately fails the +// test via tb.Fatalf() +func (t *Trap) MustWait(ctx context.Context) *Call { + t.mock.tb.Helper() + c, err := t.Wait(ctx) + if err != nil { + t.mock.tb.Fatalf("context expired while waiting for trap: %s", err.Error()) + } + return c +} diff --git a/vendor/github.com/coder/quartz/real.go b/vendor/github.com/coder/quartz/real.go new file mode 100644 index 0000000000..f39fb1163e --- /dev/null +++ b/vendor/github.com/coder/quartz/real.go @@ -0,0 +1,80 @@ +package quartz + +import ( + "context" + "time" +) + +type realClock struct{} + +func NewReal() Clock { + return realClock{} +} + +func (realClock) NewTicker(d time.Duration, _ ...string) *Ticker { + tkr := time.NewTicker(d) + return &Ticker{ticker: tkr, C: tkr.C} +} + +func (realClock) TickerFunc(ctx context.Context, d time.Duration, f func() error, _ ...string) Waiter { + ct := &realContextTicker{ + ctx: ctx, + tkr: time.NewTicker(d), + f: f, + err: make(chan error, 1), + } + go ct.run() + return ct +} + +type realContextTicker struct { + ctx context.Context + tkr *time.Ticker + f func() error + err chan error +} + +func (t *realContextTicker) Wait(_ ...string) error { + return <-t.err +} + +func (t *realContextTicker) run() { + defer t.tkr.Stop() + for { + select { + case <-t.ctx.Done(): + t.err <- t.ctx.Err() + return + case <-t.tkr.C: + err := t.f() + if err != nil { + t.err <- err + return + } + } + } +} + +func (realClock) NewTimer(d time.Duration, _ ...string) *Timer { + rt := time.NewTimer(d) + return &Timer{C: rt.C, timer: rt} +} + +func (realClock) AfterFunc(d time.Duration, f func(), _ ...string) *Timer { + rt := time.AfterFunc(d, f) + return &Timer{C: rt.C, timer: rt} +} + +func (realClock) Now(_ ...string) time.Time { + return time.Now() +} + +func (realClock) Since(t time.Time, _ ...string) time.Duration { + return time.Since(t) +} + +func (realClock) Until(t time.Time, _ ...string) time.Duration { + return time.Until(t) +} + +var _ Clock = realClock{} diff --git a/vendor/github.com/coder/quartz/ticker.go b/vendor/github.com/coder/quartz/ticker.go new file mode 100644 index 0000000000..5506750d5d --- /dev/null +++ b/vendor/github.com/coder/quartz/ticker.go @@ -0,0 +1,75 @@ +package quartz + +import "time" + +// A Ticker holds a channel that delivers “ticks” of a clock at intervals. +type Ticker struct { + C <-chan time.Time + //nolint: revive + c chan time.Time + ticker *time.Ticker // realtime impl, if set + d time.Duration // period, if set + nxt time.Time // next tick time + mock *Mock // mock clock, if set + stopped bool // true if the ticker is not running +} + +func (t *Ticker) fire(tt time.Time) { + t.mock.mu.Lock() + defer t.mock.mu.Unlock() + if t.stopped { + return + } + for !t.nxt.After(t.mock.cur) { + t.nxt = t.nxt.Add(t.d) + } + t.mock.recomputeNextLocked() + select { + case t.c <- tt: + default: + } +} + +func (t *Ticker) next() time.Time { + return t.nxt +} + +// Stop turns off a ticker. After Stop, no more ticks will be sent. Stop does +// not close the channel, to prevent a concurrent goroutine reading from the +// channel from seeing an erroneous "tick". +func (t *Ticker) Stop(tags ...string) { + if t.ticker != nil { + t.ticker.Stop() + return + } + t.mock.mu.Lock() + defer t.mock.mu.Unlock() + c := newCall(clockFunctionTickerStop, tags) + t.mock.matchCallLocked(c) + defer close(c.complete) + t.mock.removeEventLocked(t) + t.stopped = true +} + +// Reset stops a ticker and resets its period to the specified duration. The +// next tick will arrive after the new period elapses. The duration d must be +// greater than zero; if not, Reset will panic. +func (t *Ticker) Reset(d time.Duration, tags ...string) { + if t.ticker != nil { + t.ticker.Reset(d) + return + } + t.mock.mu.Lock() + defer t.mock.mu.Unlock() + c := newCall(clockFunctionTickerReset, tags, withDuration(d)) + t.mock.matchCallLocked(c) + defer close(c.complete) + t.nxt = t.mock.cur.Add(d) + t.d = d + if t.stopped { + t.stopped = false + t.mock.addEventLocked(t) + } else { + t.mock.recomputeNextLocked() + } +} diff --git a/vendor/github.com/coder/quartz/timer.go b/vendor/github.com/coder/quartz/timer.go new file mode 100644 index 0000000000..8d928ac6f6 --- /dev/null +++ b/vendor/github.com/coder/quartz/timer.go @@ -0,0 +1,81 @@ +package quartz + +import "time" + +// The Timer type represents a single event. When the Timer expires, the current time will be sent +// on C, unless the Timer was created by AfterFunc. A Timer must be created with NewTimer or +// AfterFunc. +type Timer struct { + C <-chan time.Time + //nolint: revive + c chan time.Time + timer *time.Timer // realtime impl, if set + nxt time.Time // next tick time + mock *Mock // mock clock, if set + fn func() // AfterFunc function, if set + stopped bool // True if stopped, false if running +} + +func (t *Timer) fire(tt time.Time) { + t.mock.removeTimer(t) + if t.fn != nil { + t.fn() + } else { + t.c <- tt + } +} + +func (t *Timer) next() time.Time { + return t.nxt +} + +// Stop prevents the Timer from firing. It returns true if the call stops the timer, false if the +// timer has already expired or been stopped. Stop does not close the channel, to prevent a read +// from the channel succeeding incorrectly. +// +// See https://pkg.go.dev/time#Timer.Stop for more information. +func (t *Timer) Stop(tags ...string) bool { + if t.timer != nil { + return t.timer.Stop() + } + t.mock.mu.Lock() + defer t.mock.mu.Unlock() + c := newCall(clockFunctionTimerStop, tags) + t.mock.matchCallLocked(c) + defer close(c.complete) + result := !t.stopped + t.mock.removeTimerLocked(t) + return result +} + +// Reset changes the timer to expire after duration d. It returns true if the timer had been active, +// false if the timer had expired or been stopped. +// +// See https://pkg.go.dev/time#Timer.Reset for more information. +func (t *Timer) Reset(d time.Duration, tags ...string) bool { + if t.timer != nil { + return t.timer.Reset(d) + } + t.mock.mu.Lock() + defer t.mock.mu.Unlock() + c := newCall(clockFunctionTimerReset, tags, withDuration(d)) + t.mock.matchCallLocked(c) + defer close(c.complete) + result := !t.stopped + select { + case <-t.c: + default: + } + if d <= 0 { + // zero or negative duration timer means we should immediately re-fire + // it, rather than remove and re-add it. + t.stopped = false + go t.fire(t.mock.cur) + return result + } + t.mock.removeTimerLocked(t) + t.stopped = false + t.nxt = t.mock.cur.Add(d) + t.mock.addEventLocked(t) + return result +} diff --git a/vendor/github.com/goccy/go-json/internal/decoder/compile.go b/vendor/github.com/goccy/go-json/internal/decoder/compile.go index fab6437647..8ad50936c0 100644 --- a/vendor/github.com/goccy/go-json/internal/decoder/compile.go +++ b/vendor/github.com/goccy/go-json/internal/decoder/compile.go @@ -5,6 +5,7 @@ import ( "fmt" "reflect" "strings" + "sync" "sync/atomic" "unicode" "unsafe" @@ -17,22 +18,27 @@ var ( typeAddr *runtime.TypeAddr cachedDecoderMap unsafe.Pointer // map[uintptr]decoder cachedDecoder []Decoder + initOnce sync.Once ) -func init() { - typeAddr = runtime.AnalyzeTypeAddr() - if typeAddr == nil { - typeAddr = &runtime.TypeAddr{} - } - cachedDecoder = make([]Decoder, typeAddr.AddrRange>>typeAddr.AddrShift+1) +func initDecoder() { + initOnce.Do(func() { + typeAddr = runtime.AnalyzeTypeAddr() + if typeAddr == nil { + typeAddr = &runtime.TypeAddr{} + } + cachedDecoder = make([]Decoder, typeAddr.AddrRange>>typeAddr.AddrShift+1) + }) } func loadDecoderMap() map[uintptr]Decoder { + initDecoder() p := atomic.LoadPointer(&cachedDecoderMap) return *(*map[uintptr]Decoder)(unsafe.Pointer(&p)) } func storeDecoder(typ uintptr, dec Decoder, m map[uintptr]Decoder) { + initDecoder() newDecoderMap := make(map[uintptr]Decoder, len(m)+1) newDecoderMap[typ] = dec diff --git a/vendor/github.com/goccy/go-json/internal/decoder/compile_norace.go b/vendor/github.com/goccy/go-json/internal/decoder/compile_norace.go index eb7e2b1345..025ca85b5e 100644 --- a/vendor/github.com/goccy/go-json/internal/decoder/compile_norace.go +++ b/vendor/github.com/goccy/go-json/internal/decoder/compile_norace.go @@ -10,6 +10,7 @@ import ( ) func CompileToGetDecoder(typ *runtime.Type) (Decoder, error) { + initDecoder() typeptr := uintptr(unsafe.Pointer(typ)) if typeptr > typeAddr.MaxTypeAddr { return compileToGetDecoderSlowPath(typeptr, typ) diff --git a/vendor/github.com/goccy/go-json/internal/decoder/compile_race.go b/vendor/github.com/goccy/go-json/internal/decoder/compile_race.go index 49cdda4a17..023b817c36 100644 --- a/vendor/github.com/goccy/go-json/internal/decoder/compile_race.go +++ b/vendor/github.com/goccy/go-json/internal/decoder/compile_race.go @@ -13,6 +13,7 @@ import ( var decMu sync.RWMutex func CompileToGetDecoder(typ *runtime.Type) (Decoder, error) { + initDecoder() typeptr := uintptr(unsafe.Pointer(typ)) if typeptr > typeAddr.MaxTypeAddr { return compileToGetDecoderSlowPath(typeptr, typ) diff --git a/vendor/github.com/goccy/go-json/internal/encoder/compiler.go b/vendor/github.com/goccy/go-json/internal/encoder/compiler.go index 37b7aa38e2..b107636890 100644 --- a/vendor/github.com/goccy/go-json/internal/encoder/compiler.go +++ b/vendor/github.com/goccy/go-json/internal/encoder/compiler.go @@ -5,6 +5,7 @@ import ( "encoding" "encoding/json" "reflect" + "sync" "sync/atomic" "unsafe" @@ -24,14 +25,17 @@ var ( cachedOpcodeSets []*OpcodeSet cachedOpcodeMap unsafe.Pointer // map[uintptr]*OpcodeSet typeAddr *runtime.TypeAddr + initEncoderOnce sync.Once ) -func init() { - typeAddr = runtime.AnalyzeTypeAddr() - if typeAddr == nil { - typeAddr = &runtime.TypeAddr{} - } - cachedOpcodeSets = make([]*OpcodeSet, typeAddr.AddrRange>>typeAddr.AddrShift+1) +func initEncoder() { + initEncoderOnce.Do(func() { + typeAddr = runtime.AnalyzeTypeAddr() + if typeAddr == nil { + typeAddr = &runtime.TypeAddr{} + } + cachedOpcodeSets = make([]*OpcodeSet, typeAddr.AddrRange>>typeAddr.AddrShift+1) + }) } func loadOpcodeMap() map[uintptr]*OpcodeSet { diff --git a/vendor/github.com/goccy/go-json/internal/encoder/compiler_norace.go b/vendor/github.com/goccy/go-json/internal/encoder/compiler_norace.go index 20c93cbf70..b6f45a49b0 100644 --- a/vendor/github.com/goccy/go-json/internal/encoder/compiler_norace.go +++ b/vendor/github.com/goccy/go-json/internal/encoder/compiler_norace.go @@ -4,6 +4,7 @@ package encoder func CompileToGetCodeSet(ctx *RuntimeContext, typeptr uintptr) (*OpcodeSet, error) { + initEncoder() if typeptr > typeAddr.MaxTypeAddr || typeptr < typeAddr.BaseTypeAddr { codeSet, err := compileToGetCodeSetSlowPath(typeptr) if err != nil { diff --git a/vendor/github.com/goccy/go-json/internal/encoder/compiler_race.go b/vendor/github.com/goccy/go-json/internal/encoder/compiler_race.go index 13ba23fdff..47b482f7fb 100644 --- a/vendor/github.com/goccy/go-json/internal/encoder/compiler_race.go +++ b/vendor/github.com/goccy/go-json/internal/encoder/compiler_race.go @@ -10,6 +10,7 @@ import ( var setsMu sync.RWMutex func CompileToGetCodeSet(ctx *RuntimeContext, typeptr uintptr) (*OpcodeSet, error) { + initEncoder() if typeptr > typeAddr.MaxTypeAddr || typeptr < typeAddr.BaseTypeAddr { codeSet, err := compileToGetCodeSetSlowPath(typeptr) if err != nil { diff --git a/vendor/github.com/goccy/go-json/internal/encoder/encoder.go b/vendor/github.com/goccy/go-json/internal/encoder/encoder.go index 14eb6a0d64..b436f5b21f 100644 --- a/vendor/github.com/goccy/go-json/internal/encoder/encoder.go +++ b/vendor/github.com/goccy/go-json/internal/encoder/encoder.go @@ -406,6 +406,11 @@ func AppendMarshalJSON(ctx *RuntimeContext, code *Opcode, b []byte, v interface{ rv = newV } } + + if rv.Kind() == reflect.Ptr && rv.IsNil() { + return AppendNull(ctx, b), nil + } + v = rv.Interface() var bb []byte if (code.Flags & MarshalerContextFlags) != 0 { diff --git a/vendor/github.com/golang-migrate/migrate/v4/migrate.go b/vendor/github.com/golang-migrate/migrate/v4/migrate.go index 7763782a0c..44efe14e30 100644 --- a/vendor/github.com/golang-migrate/migrate/v4/migrate.go +++ b/vendor/github.com/golang-migrate/migrate/v4/migrate.go @@ -107,7 +107,7 @@ func New(sourceURL, databaseURL string) (*Migrate, error) { databaseDrv, err := database.Open(databaseURL) if err != nil { - return nil, fmt.Errorf("failed to open database, %q: %w", databaseURL, err) + return nil, fmt.Errorf("failed to open database: %w", err) } m.databaseDrv = databaseDrv @@ -157,7 +157,7 @@ func NewWithSourceInstance(sourceName string, sourceInstance source.Driver, data databaseDrv, err := database.Open(databaseURL) if err != nil { - return nil, fmt.Errorf("failed to open database, %q: %w", databaseURL, err) + return nil, fmt.Errorf("failed to open database: %w", err) } m.databaseDrv = databaseDrv diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/query.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/query.go index 93fb09922f..0a1ca7e06f 100644 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/query.go +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/query.go @@ -141,7 +141,7 @@ func populateFieldValueFromPath(msgValue protoreflect.Message, fieldPath []strin } // Check if oneof already set - if of := fieldDescriptor.ContainingOneof(); of != nil { + if of := fieldDescriptor.ContainingOneof(); of != nil && !of.IsSynthetic() { if f := msgValue.WhichOneof(of); f != nil { return fmt.Errorf("field already set for oneof %q", of.FullName().Name()) } diff --git a/vendor/github.com/jessevdk/go-flags/.travis.yml b/vendor/github.com/jessevdk/go-flags/.travis.yml deleted file mode 100644 index 2fc5e5f5b5..0000000000 --- a/vendor/github.com/jessevdk/go-flags/.travis.yml +++ /dev/null @@ -1,39 +0,0 @@ -language: go - -os: - - linux - - osx - -go: - - 1.16.x - -install: - # go-flags - - go build -v ./... - - # linting - - go get -v golang.org/x/lint/golint - - # code coverage - - go get golang.org/x/tools/cmd/cover - - go get github.com/onsi/ginkgo/ginkgo - - go get github.com/modocache/gover - - if [ "$TRAVIS_SECURE_ENV_VARS" = "true" ]; then go get github.com/mattn/goveralls; fi - -script: - # go-flags - - $(exit $(gofmt -l . | wc -l)) - - go test -v ./... - - # linting - - go tool vet -all=true -v=true . || true - - $(go env GOPATH | awk 'BEGIN{FS=":"} {print $1}')/bin/golint ./... - - # code coverage - - $(go env GOPATH | awk 'BEGIN{FS=":"} {print $1}')/bin/ginkgo -r -cover - - $(go env GOPATH | awk 'BEGIN{FS=":"} {print $1}')/bin/gover - - if [ "$TRAVIS_SECURE_ENV_VARS" = "true" ]; then $(go env GOPATH | awk 'BEGIN{FS=":"} {print $1}')/bin/goveralls -coverprofile=gover.coverprofile -service=travis-ci -repotoken $COVERALLS_TOKEN; fi - -env: - # coveralls.io - secure: "RCYbiB4P0RjQRIoUx/vG/AjP3mmYCbzOmr86DCww1Z88yNcy3hYr3Cq8rpPtYU5v0g7wTpu4adaKIcqRE9xknYGbqj3YWZiCoBP1/n4Z+9sHW3Dsd9D/GRGeHUus0laJUGARjWoCTvoEtOgTdGQDoX7mH+pUUY0FBltNYUdOiiU=" diff --git a/vendor/github.com/jessevdk/go-flags/README.md b/vendor/github.com/jessevdk/go-flags/README.md index f22650b20a..759eeb0d4e 100644 --- a/vendor/github.com/jessevdk/go-flags/README.md +++ b/vendor/github.com/jessevdk/go-flags/README.md @@ -1,7 +1,7 @@ go-flags: a go library for parsing command line arguments ========================================================= -[![GoDoc](https://godoc.org/github.com/jessevdk/go-flags?status.png)](https://godoc.org/github.com/jessevdk/go-flags) [![Build Status](https://travis-ci.org/jessevdk/go-flags.svg?branch=master)](https://travis-ci.org/jessevdk/go-flags) [![Coverage Status](https://img.shields.io/coveralls/jessevdk/go-flags.svg)](https://coveralls.io/r/jessevdk/go-flags?branch=master) +[![GoDoc](https://godoc.org/github.com/jessevdk/go-flags?status.png)](https://godoc.org/github.com/jessevdk/go-flags) This library provides similar functionality to the builtin flag library of go, but provides much more functionality and nicer formatting. From the @@ -78,6 +78,9 @@ var opts struct { // Example of a map IntMap map[string]int `long:"intmap" description:"A map from string to int"` + + // Example of env variable + Thresholds []int `long:"thresholds" default:"1" default:"2" env:"THRESHOLD_VALUES" env-delim:","` } // Callback which will invoke callto: to call a number. diff --git a/vendor/github.com/jessevdk/go-flags/command.go b/vendor/github.com/jessevdk/go-flags/command.go index 879465d7a5..ac4f1e392b 100644 --- a/vendor/github.com/jessevdk/go-flags/command.go +++ b/vendor/github.com/jessevdk/go-flags/command.go @@ -30,6 +30,12 @@ type Command struct { // Whether positional arguments are required ArgsRequired bool + // Whether to pass all arguments after the first non option as remaining + // command line arguments. This is equivalent to strict POSIX processing. + // This is command-local version of PassAfterNonOption Parser flag. It + // cannot be turned off when PassAfterNonOption Parser flag is set. + PassAfterNonOption bool + commands []*Command hasBuiltinHelpGroup bool args []*Arg @@ -244,6 +250,7 @@ func (c *Command) scanSubcommandHandler(parentg *Group) scanHandler { longDescription := mtag.Get("long-description") subcommandsOptional := mtag.Get("subcommands-optional") aliases := mtag.GetMany("alias") + passAfterNonOption := mtag.Get("pass-after-non-option") subc, err := c.AddCommand(subcommand, shortDescription, longDescription, ptrval.Interface()) @@ -261,6 +268,10 @@ func (c *Command) scanSubcommandHandler(parentg *Group) scanHandler { subc.Aliases = aliases } + if len(passAfterNonOption) > 0 { + subc.PassAfterNonOption = true + } + return true, nil } diff --git a/vendor/github.com/jessevdk/go-flags/convert.go b/vendor/github.com/jessevdk/go-flags/convert.go index cda29b2f04..b27f698dc4 100644 --- a/vendor/github.com/jessevdk/go-flags/convert.go +++ b/vendor/github.com/jessevdk/go-flags/convert.go @@ -53,7 +53,7 @@ func getBase(options multiTag, base int) (int, error) { func convertMarshal(val reflect.Value) (bool, string, error) { // Check first for the Marshaler interface - if val.Type().NumMethod() > 0 && val.CanInterface() { + if val.IsValid() && val.Type().NumMethod() > 0 && val.CanInterface() { if marshaler, ok := val.Interface().(Marshaler); ok { ret, err := marshaler.MarshalFlag() return true, ret, err @@ -68,6 +68,10 @@ func convertToString(val reflect.Value, options multiTag) (string, error) { return ret, err } + if !val.IsValid() { + return "", nil + } + tp := val.Type() // Support for time.Duration @@ -220,7 +224,7 @@ func convert(val string, retval reflect.Value, options multiTag) error { retval.SetBool(b) } case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - base, err := getBase(options, 10) + base, err := getBase(options, 0) if err != nil { return err @@ -234,7 +238,7 @@ func convert(val string, retval reflect.Value, options multiTag) error { retval.SetInt(parsed) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - base, err := getBase(options, 10) + base, err := getBase(options, 0) if err != nil { return err @@ -267,7 +271,12 @@ func convert(val string, retval reflect.Value, options multiTag) error { retval.Set(reflect.Append(retval, elemval)) case reflect.Map: - parts := strings.SplitN(val, ":", 2) + keyValueDelimiter := options.Get("key-value-delimiter") + if keyValueDelimiter == "" { + keyValueDelimiter = ":" + } + + parts := strings.SplitN(val, keyValueDelimiter, 2) key := parts[0] var value string diff --git a/vendor/github.com/jessevdk/go-flags/flags.go b/vendor/github.com/jessevdk/go-flags/flags.go index ac2157dd60..a6acf1be1f 100644 --- a/vendor/github.com/jessevdk/go-flags/flags.go +++ b/vendor/github.com/jessevdk/go-flags/flags.go @@ -8,46 +8,45 @@ The flags package is similar in functionality to the go built-in flag package but provides more options and uses reflection to provide a convenient and succinct way of specifying command line options. - -Supported features +# Supported features The following features are supported in go-flags: - Options with short names (-v) - Options with long names (--verbose) - Options with and without arguments (bool v.s. other type) - Options with optional arguments and default values - Option default values from ENVIRONMENT_VARIABLES, including slice and map values - Multiple option groups each containing a set of options - Generate and print well-formatted help message - Passing remaining command line arguments after -- (optional) - Ignoring unknown command line options (optional) - Supports -I/usr/include -I=/usr/include -I /usr/include option argument specification - Supports multiple short options -aux - Supports all primitive go types (string, int{8..64}, uint{8..64}, float) - Supports same option multiple times (can store in slice or last option counts) - Supports maps - Supports function callbacks - Supports namespaces for (nested) option groups + Options with short names (-v) + Options with long names (--verbose) + Options with and without arguments (bool v.s. other type) + Options with optional arguments and default values + Option default values from ENVIRONMENT_VARIABLES, including slice and map values + Multiple option groups each containing a set of options + Generate and print well-formatted help message + Passing remaining command line arguments after -- (optional) + Ignoring unknown command line options (optional) + Supports -I/usr/include -I=/usr/include -I /usr/include option argument specification + Supports multiple short options -aux + Supports all primitive go types (string, int{8..64}, uint{8..64}, float) + Supports same option multiple times (can store in slice or last option counts) + Supports maps + Supports function callbacks + Supports namespaces for (nested) option groups Additional features specific to Windows: - Options with short names (/v) - Options with long names (/verbose) - Windows-style options with arguments use a colon as the delimiter - Modify generated help message with Windows-style / options - Windows style options can be disabled at build time using the "forceposix" - build tag + Options with short names (/v) + Options with long names (/verbose) + Windows-style options with arguments use a colon as the delimiter + Modify generated help message with Windows-style / options + Windows style options can be disabled at build time using the "forceposix" + build tag -Basic usage +# Basic usage The flags package uses structs, reflection and struct field tags to allow users to specify command line options. This results in very simple and concise specification of your application options. For example: - type Options struct { - Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"` - } + type Options struct { + Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"` + } This specifies one option with a short name -v and a long name --verbose. When either -v or --verbose is found on the command line, a 'true' value @@ -60,9 +59,9 @@ whenever the option is encountered, a value is appended to the slice. Map options from string to primitive type are also supported. On the command line, you specify the value for such an option as key:value. For example - type Options struct { - AuthorInfo string[string] `short:"a"` - } + type Options struct { + AuthorInfo string[string] `short:"a"` + } Then, the AuthorInfo map can be filled with something like -a name:Jesse -a "surname:van den Kieboom". @@ -71,96 +70,94 @@ Finally, for full control over the conversion between command line argument values and options, user defined types can choose to implement the Marshaler and Unmarshaler interfaces. - -Available field tags +# Available field tags The following is a list of tags for struct fields supported by go-flags: - short: the short name of the option (single character) - long: the long name of the option - required: if non empty, makes the option required to appear on the command - line. If a required option is not present, the parser will - return ErrRequired (optional) - description: the description of the option (optional) - long-description: the long description of the option. Currently only - displayed in generated man pages (optional) - no-flag: if non-empty, this field is ignored as an option (optional) - - optional: if non-empty, makes the argument of the option optional. When an - argument is optional it can only be specified using - --option=argument (optional) - optional-value: the value of an optional option when the option occurs - without an argument. This tag can be specified multiple - times in the case of maps or slices (optional) - default: the default value of an option. This tag can be specified - multiple times in the case of slices or maps (optional) - default-mask: when specified, this value will be displayed in the help - instead of the actual default value. This is useful - mostly for hiding otherwise sensitive information from - showing up in the help. If default-mask takes the special - value "-", then no default value will be shown at all - (optional) - env: the default value of the option is overridden from the - specified environment variable, if one has been defined. - (optional) - env-delim: the 'env' default value from environment is split into - multiple values with the given delimiter string, use with - slices and maps (optional) - value-name: the name of the argument value (to be shown in the help) - (optional) - choice: limits the values for an option to a set of values. - Repeat this tag once for each allowable value. - e.g. `long:"animal" choice:"cat" choice:"dog"` - hidden: if non-empty, the option is not visible in the help or man page. - - base: a base (radix) used to convert strings to integer values, the - default base is 10 (i.e. decimal) (optional) - - ini-name: the explicit ini option name (optional) - no-ini: if non-empty this field is ignored as an ini option - (optional) - - group: when specified on a struct field, makes the struct - field a separate group with the given name (optional) - namespace: when specified on a group struct field, the namespace - gets prepended to every option's long name and - subgroup's namespace of this group, separated by - the parser's namespace delimiter (optional) - env-namespace: when specified on a group struct field, the env-namespace - gets prepended to every option's env key and - subgroup's env-namespace of this group, separated by - the parser's env-namespace delimiter (optional) - command: when specified on a struct field, makes the struct - field a (sub)command with the given name (optional) - subcommands-optional: when specified on a command struct field, makes - any subcommands of that command optional (optional) - alias: when specified on a command struct field, adds the - specified name as an alias for the command. Can be - be specified multiple times to add more than one - alias (optional) - positional-args: when specified on a field with a struct type, - uses the fields of that struct to parse remaining - positional command line arguments into (in order - of the fields). If a field has a slice type, - then all remaining arguments will be added to it. - Positional arguments are optional by default, - unless the "required" tag is specified together - with the "positional-args" tag. The "required" tag - can also be set on the individual rest argument - fields, to require only the first N positional - arguments. If the "required" tag is set on the - rest arguments slice, then its value determines - the minimum amount of rest arguments that needs to - be provided (e.g. `required:"2"`) (optional) - positional-arg-name: used on a field in a positional argument struct; name - of the positional argument placeholder to be shown in - the help (optional) + short: the short name of the option (single character) + long: the long name of the option + required: if non empty, makes the option required to appear on the command + line. If a required option is not present, the parser will + return ErrRequired (optional) + description: the description of the option (optional) + long-description: the long description of the option. Currently only + displayed in generated man pages (optional) + no-flag: if non-empty, this field is ignored as an option (optional) + + optional: if non-empty, makes the argument of the option optional. When an + argument is optional it can only be specified using + --option=argument (optional) + optional-value: the value of an optional option when the option occurs + without an argument. This tag can be specified multiple + times in the case of maps or slices (optional) + default: the default value of an option. This tag can be specified + multiple times in the case of slices or maps (optional) + default-mask: when specified, this value will be displayed in the help + instead of the actual default value. This is useful + mostly for hiding otherwise sensitive information from + showing up in the help. If default-mask takes the special + value "-", then no default value will be shown at all + (optional) + env: the default value of the option is overridden from the + specified environment variable, if one has been defined. + (optional) + env-delim: the 'env' default value from environment is split into + multiple values with the given delimiter string, use with + slices and maps (optional) + value-name: the name of the argument value (to be shown in the help) + (optional) + choice: limits the values for an option to a set of values. + Repeat this tag once for each allowable value. + e.g. `long:"animal" choice:"cat" choice:"dog"` + hidden: if non-empty, the option is not visible in the help or man page. + + base: a base (radix) used to convert strings to integer values, the + default base is 10 (i.e. decimal) (optional) + + ini-name: the explicit ini option name (optional) + no-ini: if non-empty this field is ignored as an ini option + (optional) + + group: when specified on a struct field, makes the struct + field a separate group with the given name (optional) + namespace: when specified on a group struct field, the namespace + gets prepended to every option's long name and + subgroup's namespace of this group, separated by + the parser's namespace delimiter (optional) + env-namespace: when specified on a group struct field, the env-namespace + gets prepended to every option's env key and + subgroup's env-namespace of this group, separated by + the parser's env-namespace delimiter (optional) + command: when specified on a struct field, makes the struct + field a (sub)command with the given name (optional) + subcommands-optional: when specified on a command struct field, makes + any subcommands of that command optional (optional) + alias: when specified on a command struct field, adds the + specified name as an alias for the command. Can be + be specified multiple times to add more than one + alias (optional) + positional-args: when specified on a field with a struct type, + uses the fields of that struct to parse remaining + positional command line arguments into (in order + of the fields). If a field has a slice type, + then all remaining arguments will be added to it. + Positional arguments are optional by default, + unless the "required" tag is specified together + with the "positional-args" tag. The "required" tag + can also be set on the individual rest argument + fields, to require only the first N positional + arguments. If the "required" tag is set on the + rest arguments slice, then its value determines + the minimum amount of rest arguments that needs to + be provided (e.g. `required:"2"`) (optional) + positional-arg-name: used on a field in a positional argument struct; name + of the positional argument placeholder to be shown in + the help (optional) Either the `short:` tag or the `long:` must be specified to make the field eligible as an option. - -Option groups +# Option groups Option groups are a simple way to semantically separate your options. All options in a particular group are shown together in the help under the name @@ -169,14 +166,12 @@ precisely and emphasize the options affiliation to their group. There are currently three ways to specify option groups. - 1. Use NewNamedParser specifying the various option groups. - 2. Use AddGroup to add a group to an existing parser. - 3. Add a struct field to the top-level options annotated with the - group:"group-name" tag. + 1. Use NewNamedParser specifying the various option groups. + 2. Use AddGroup to add a group to an existing parser. + 3. Add a struct field to the top-level options annotated with the + group:"group-name" tag. - - -Commands +# Commands The flags package also has basic support for commands. Commands are often used in monolithic applications that support various commands or actions. @@ -186,9 +181,9 @@ application. There are currently two ways to specify a command. - 1. Use AddCommand on an existing parser. - 2. Add a struct field to your options struct annotated with the - command:"command-name" tag. + 1. Use AddCommand on an existing parser. + 2. Add a struct field to your options struct annotated with the + command:"command-name" tag. The most common, idiomatic way to implement commands is to define a global parser instance and implement each command in a separate file. These @@ -204,15 +199,14 @@ command has been specified on the command line, in addition to the options of all the parent commands. I.e. considering a -v flag on the parser and an add command, the following are equivalent: - ./app -v add - ./app add -v + ./app -v add + ./app add -v However, if the -v flag is defined on the add command, then the first of the two examples above would fail since the -v flag is not defined before the add command. - -Completion +# Completion go-flags has builtin support to provide bash completion of flags, commands and argument values. To use completion, the binary which uses go-flags @@ -226,7 +220,7 @@ by replacing the argument parsing routine with the completion routine which outputs completions for the passed arguments. The basic invocation to complete a set of arguments is therefore: - GO_FLAGS_COMPLETION=1 ./completion-example arg1 arg2 arg3 + GO_FLAGS_COMPLETION=1 ./completion-example arg1 arg2 arg3 where `completion-example` is the binary, `arg1` and `arg2` are the current arguments, and `arg3` (the last argument) is the argument @@ -237,20 +231,20 @@ are more than 1 completion items. To use this with bash completion, a simple file can be written which calls the binary which supports go-flags completion: - _completion_example() { - # All arguments except the first one - args=("${COMP_WORDS[@]:1:$COMP_CWORD}") + _completion_example() { + # All arguments except the first one + args=("${COMP_WORDS[@]:1:$COMP_CWORD}") - # Only split on newlines - local IFS=$'\n' + # Only split on newlines + local IFS=$'\n' - # Call completion (note that the first element of COMP_WORDS is - # the executable itself) - COMPREPLY=($(GO_FLAGS_COMPLETION=1 ${COMP_WORDS[0]} "${args[@]}")) - return 0 - } + # Call completion (note that the first element of COMP_WORDS is + # the executable itself) + COMPREPLY=($(GO_FLAGS_COMPLETION=1 ${COMP_WORDS[0]} "${args[@]}")) + return 0 + } - complete -F _completion_example completion-example + complete -F _completion_example completion-example Completion requires the parser option PassDoubleDash and is therefore enforced if the environment variable GO_FLAGS_COMPLETION is set. diff --git a/vendor/github.com/jessevdk/go-flags/help.go b/vendor/github.com/jessevdk/go-flags/help.go index 068fce1525..8fd324443a 100644 --- a/vendor/github.com/jessevdk/go-flags/help.go +++ b/vendor/github.com/jessevdk/go-flags/help.go @@ -72,15 +72,15 @@ func (p *Parser) getAlignmentInfo() alignmentInfo { var prevcmd *Command p.eachActiveGroup(func(c *Command, grp *Group) { - if !grp.showInHelp() { - return - } if c != prevcmd { for _, arg := range c.args { ret.updateLen(arg.Name, c != p.Command) } + prevcmd = c + } + if !grp.showInHelp() { + return } - for _, info := range grp.options { if !info.showInHelp() { continue @@ -334,7 +334,11 @@ func (p *Parser) WriteHelp(writer io.Writer) { } if !allcmd.ArgsRequired { - fmt.Fprintf(wr, "[%s]", name) + if arg.Required > 0 { + fmt.Fprintf(wr, "%s", name) + } else { + fmt.Fprintf(wr, "[%s]", name) + } } else { fmt.Fprintf(wr, "%s", name) } diff --git a/vendor/github.com/jessevdk/go-flags/ini.go b/vendor/github.com/jessevdk/go-flags/ini.go index 60b36c79c4..565595e5f1 100644 --- a/vendor/github.com/jessevdk/go-flags/ini.go +++ b/vendor/github.com/jessevdk/go-flags/ini.go @@ -113,18 +113,18 @@ func (i *IniParser) ParseFile(filename string) error { // // The format of the ini file is as follows: // -// [Option group name] -// option = value +// [Option group name] +// option = value // // Each section in the ini file represents an option group or command in the // flags parser. The default flags parser option group (i.e. when using // flags.Parse) is named 'Application Options'. The ini option name is matched // in the following order: // -// 1. Compared to the ini-name tag on the option struct field (if present) -// 2. Compared to the struct field name -// 3. Compared to the option long name (if present) -// 4. Compared to the option short name (if present) +// 1. Compared to the ini-name tag on the option struct field (if present) +// 2. Compared to the struct field name +// 3. Compared to the option long name (if present) +// 4. Compared to the option short name (if present) // // Sections for nested groups and commands can be addressed using a dot `.' // namespacing notation (i.e [subcommand.Options]). Group section names are @@ -584,7 +584,7 @@ func (i *IniParser) parse(ini *ini) error { if i.ParseAsDefaults { err = opt.setDefault(pval) } else { - err = opt.set(pval) + err = opt.Set(pval) } if err != nil { diff --git a/vendor/github.com/jessevdk/go-flags/option.go b/vendor/github.com/jessevdk/go-flags/option.go index f6d6941813..257996a792 100644 --- a/vendor/github.com/jessevdk/go-flags/option.go +++ b/vendor/github.com/jessevdk/go-flags/option.go @@ -239,7 +239,7 @@ func (option *Option) IsSetDefault() bool { // Set the value of an option to the specified value. An error will be returned // if the specified value could not be converted to the corresponding option // value type. -func (option *Option) set(value *string) error { +func (option *Option) Set(value *string) error { kind := option.value.Type().Kind() if (kind == reflect.Map || kind == reflect.Slice) && option.clearReferenceBeforeSet { @@ -287,7 +287,7 @@ func (option *Option) setDefault(value *string) error { return nil } - if err := option.set(value); err != nil { + if err := option.Set(value); err != nil { return err } diff --git a/vendor/github.com/jessevdk/go-flags/optstyle_other.go b/vendor/github.com/jessevdk/go-flags/optstyle_other.go index 56dfdae128..f84b69746d 100644 --- a/vendor/github.com/jessevdk/go-flags/optstyle_other.go +++ b/vendor/github.com/jessevdk/go-flags/optstyle_other.go @@ -1,3 +1,4 @@ +//go:build !windows || forceposix // +build !windows forceposix package flags diff --git a/vendor/github.com/jessevdk/go-flags/optstyle_windows.go b/vendor/github.com/jessevdk/go-flags/optstyle_windows.go index f3f28aeeff..e80290420a 100644 --- a/vendor/github.com/jessevdk/go-flags/optstyle_windows.go +++ b/vendor/github.com/jessevdk/go-flags/optstyle_windows.go @@ -1,3 +1,4 @@ +//go:build !forceposix // +build !forceposix package flags diff --git a/vendor/github.com/jessevdk/go-flags/parser.go b/vendor/github.com/jessevdk/go-flags/parser.go index 3fc3f7ba1c..939dd7bf49 100644 --- a/vendor/github.com/jessevdk/go-flags/parser.go +++ b/vendor/github.com/jessevdk/go-flags/parser.go @@ -113,6 +113,10 @@ const ( // POSIX processing. PassAfterNonOption + // AllowBoolValues allows a user to assign true/false to a boolean value + // rather than raising an error stating it cannot have an argument. + AllowBoolValues + // Default is a convenient default set of options which should cover // most of the uses of the flags package. Default = HelpFlag | PrintErrors | PassDoubleDash @@ -252,7 +256,7 @@ func (p *Parser) ParseArgs(args []string) ([]string, error) { } if !argumentIsOption(arg) { - if (p.Options&PassAfterNonOption) != None && s.lookup.commands[arg] == nil { + if ((p.Options&PassAfterNonOption) != None || s.command.PassAfterNonOption) && s.lookup.commands[arg] == nil { // If PassAfterNonOption is set then all remaining arguments // are considered positional if err = s.addArgs(s.arg); err != nil { @@ -521,11 +525,10 @@ func (p *parseState) estimateCommand() error { func (p *Parser) parseOption(s *parseState, name string, option *Option, canarg bool, argument *string) (err error) { if !option.canArgument() { - if argument != nil { + if argument != nil && (p.Options&AllowBoolValues) == None { return newErrorf(ErrNoArgumentForBool, "bool flag `%s' cannot have an argument", option) } - - err = option.set(nil) + err = option.Set(argument) } else if argument != nil || (canarg && !s.eof()) { var arg string @@ -546,13 +549,13 @@ func (p *Parser) parseOption(s *parseState, name string, option *Option, canarg } if err == nil { - err = option.set(&arg) + err = option.Set(&arg) } } else if option.OptionalArgument { option.empty() for _, v := range option.OptionalValue { - err = option.set(&v) + err = option.Set(&v) if err != nil { break diff --git a/vendor/github.com/jessevdk/go-flags/termsize.go b/vendor/github.com/jessevdk/go-flags/termsize.go index 829e477add..7bcf66feeb 100644 --- a/vendor/github.com/jessevdk/go-flags/termsize.go +++ b/vendor/github.com/jessevdk/go-flags/termsize.go @@ -1,4 +1,5 @@ -// +build !windows,!plan9,!appengine,!wasm +//go:build !windows && !plan9 && !appengine && !wasm && !aix +// +build !windows,!plan9,!appengine,!wasm,!aix package flags diff --git a/vendor/github.com/jessevdk/go-flags/termsize_nosysioctl.go b/vendor/github.com/jessevdk/go-flags/termsize_nosysioctl.go index c1ff18673b..d839220aa5 100644 --- a/vendor/github.com/jessevdk/go-flags/termsize_nosysioctl.go +++ b/vendor/github.com/jessevdk/go-flags/termsize_nosysioctl.go @@ -1,4 +1,5 @@ -// +build plan9 appengine wasm +//go:build plan9 || appengine || wasm || aix +// +build plan9 appengine wasm aix package flags diff --git a/vendor/github.com/jessevdk/go-flags/termsize_windows.go b/vendor/github.com/jessevdk/go-flags/termsize_windows.go index 5c0fa6ba27..189a1b3faf 100644 --- a/vendor/github.com/jessevdk/go-flags/termsize_windows.go +++ b/vendor/github.com/jessevdk/go-flags/termsize_windows.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package flags diff --git a/vendor/github.com/klauspost/cpuid/v2/README.md b/vendor/github.com/klauspost/cpuid/v2/README.md index 21508edbdb..f06ba51c56 100644 --- a/vendor/github.com/klauspost/cpuid/v2/README.md +++ b/vendor/github.com/klauspost/cpuid/v2/README.md @@ -281,6 +281,7 @@ Exit Code 1 | AMXBF16 | Tile computational operations on BFLOAT16 numbers | | AMXINT8 | Tile computational operations on 8-bit integers | | AMXFP16 | Tile computational operations on FP16 numbers | +| AMXFP8 | Tile computational operations on FP8 numbers | | AMXTILE | Tile architecture | | APX_F | Intel APX | | AVX | AVX functions | diff --git a/vendor/github.com/klauspost/cpuid/v2/cpuid.go b/vendor/github.com/klauspost/cpuid/v2/cpuid.go index 53bc18ca71..db99eb62f7 100644 --- a/vendor/github.com/klauspost/cpuid/v2/cpuid.go +++ b/vendor/github.com/klauspost/cpuid/v2/cpuid.go @@ -55,6 +55,12 @@ const ( Qualcomm Marvell + QEMU + QNX + ACRN + SRE + Apple + lastVendor ) @@ -75,6 +81,7 @@ const ( AMXBF16 // Tile computational operations on BFLOAT16 numbers AMXFP16 // Tile computational operations on FP16 numbers AMXINT8 // Tile computational operations on 8-bit integers + AMXFP8 // Tile computational operations on FP8 numbers AMXTILE // Tile architecture APX_F // Intel APX AVX // AVX functions @@ -296,20 +303,22 @@ const ( // CPUInfo contains information about the detected system CPU. type CPUInfo struct { - BrandName string // Brand name reported by the CPU - VendorID Vendor // Comparable CPU vendor ID - VendorString string // Raw vendor string. - featureSet flagSet // Features of the CPU - PhysicalCores int // Number of physical processor cores in your CPU. Will be 0 if undetectable. - ThreadsPerCore int // Number of threads per physical core. Will be 1 if undetectable. - LogicalCores int // Number of physical cores times threads that can run on each core through the use of hyperthreading. Will be 0 if undetectable. - Family int // CPU family number - Model int // CPU model number - Stepping int // CPU stepping info - CacheLine int // Cache line size in bytes. Will be 0 if undetectable. - Hz int64 // Clock speed, if known, 0 otherwise. Will attempt to contain base clock speed. - BoostFreq int64 // Max clock speed, if known, 0 otherwise - Cache struct { + BrandName string // Brand name reported by the CPU + VendorID Vendor // Comparable CPU vendor ID + VendorString string // Raw vendor string. + HypervisorVendorID Vendor // Hypervisor vendor + HypervisorVendorString string // Raw hypervisor vendor string + featureSet flagSet // Features of the CPU + PhysicalCores int // Number of physical processor cores in your CPU. Will be 0 if undetectable. + ThreadsPerCore int // Number of threads per physical core. Will be 1 if undetectable. + LogicalCores int // Number of physical cores times threads that can run on each core through the use of hyperthreading. Will be 0 if undetectable. + Family int // CPU family number + Model int // CPU model number + Stepping int // CPU stepping info + CacheLine int // Cache line size in bytes. Will be 0 if undetectable. + Hz int64 // Clock speed, if known, 0 otherwise. Will attempt to contain base clock speed. + BoostFreq int64 // Max clock speed, if known, 0 otherwise + Cache struct { L1I int // L1 Instruction Cache (per core or shared). Will be -1 if undetected L1D int // L1 Data Cache (per core or shared). Will be -1 if undetected L2 int // L2 Cache (per core or shared). Will be -1 if undetected @@ -318,8 +327,9 @@ type CPUInfo struct { SGX SGXSupport AMDMemEncryption AMDMemEncryptionSupport AVX10Level uint8 - maxFunc uint32 - maxExFunc uint32 + + maxFunc uint32 + maxExFunc uint32 } var cpuid func(op uint32) (eax, ebx, ecx, edx uint32) @@ -503,7 +513,7 @@ func (c CPUInfo) FeatureSet() []string { // Uses the RDTSCP instruction. The value 0 is returned // if the CPU does not support the instruction. func (c CPUInfo) RTCounter() uint64 { - if !c.Supports(RDTSCP) { + if !c.Has(RDTSCP) { return 0 } a, _, _, d := rdtscpAsm() @@ -515,13 +525,22 @@ func (c CPUInfo) RTCounter() uint64 { // about the current cpu/core the code is running on. // If the RDTSCP instruction isn't supported on the CPU, the value 0 is returned. func (c CPUInfo) Ia32TscAux() uint32 { - if !c.Supports(RDTSCP) { + if !c.Has(RDTSCP) { return 0 } _, _, ecx, _ := rdtscpAsm() return ecx } +// SveLengths returns arm SVE vector and predicate lengths. +// Will return 0, 0 if SVE is not enabled or otherwise unable to detect. +func (c CPUInfo) SveLengths() (vl, pl uint64) { + if !c.Has(SVE) { + return 0, 0 + } + return getVectorLength() +} + // LogicalCPU will return the Logical CPU the code is currently executing on. // This is likely to change when the OS re-schedules the running thread // to another CPU. @@ -781,11 +800,16 @@ func threadsPerCore() int { _, b, _, _ := cpuidex(0xb, 0) if b&0xffff == 0 { if vend == AMD { - // Workaround for AMD returning 0, assume 2 if >= Zen 2 - // It will be more correct than not. + // if >= Zen 2 0x8000001e EBX 15-8 bits means threads per core. + // The number of threads per core is ThreadsPerCore+1 + // See PPR for AMD Family 17h Models 00h-0Fh (page 82) fam, _, _ := familyModel() _, _, _, d := cpuid(1) if (d&(1<<28)) != 0 && fam >= 23 { + if maxExtendedFunction() >= 0x8000001e { + _, b, _, _ := cpuid(0x8000001e) + return int((b>>8)&0xff) + 1 + } return 2 } } @@ -877,7 +901,9 @@ var vendorMapping = map[string]Vendor{ "GenuineTMx86": Transmeta, "Geode by NSC": NSC, "VIA VIA VIA ": VIA, - "KVMKVMKVMKVM": KVM, + "KVMKVMKVM": KVM, + "Linux KVM Hv": KVM, + "TCGTCGTCGTCG": QEMU, "Microsoft Hv": MSVM, "VMwareVMware": VMware, "XenVMMXenVMM": XenHVM, @@ -887,6 +913,10 @@ var vendorMapping = map[string]Vendor{ "SiS SiS SiS ": SiS, "RiseRiseRise": SiS, "Genuine RDC": RDC, + "QNXQVMBSQG": QNX, + "ACRNACRNACRN": ACRN, + "SRESRESRESRE": SRE, + "Apple VZ": Apple, } func vendorID() (Vendor, string) { @@ -899,6 +929,17 @@ func vendorID() (Vendor, string) { return vend, v } +func hypervisorVendorID() (Vendor, string) { + // https://lwn.net/Articles/301888/ + _, b, c, d := cpuid(0x40000000) + v := string(valAsString(b, c, d)) + vend, ok := vendorMapping[v] + if !ok { + return VendorUnknown, v + } + return vend, v +} + func cacheLine() int { if maxFunctionID() < 0x1 { return 0 @@ -1271,6 +1312,7 @@ func support() flagSet { fs.setIf(ebx&(1<<31) != 0, AVX512VL) // ecx fs.setIf(ecx&(1<<1) != 0, AVX512VBMI) + fs.setIf(ecx&(1<<3) != 0, AMXFP8) fs.setIf(ecx&(1<<6) != 0, AVX512VBMI2) fs.setIf(ecx&(1<<11) != 0, AVX512VNNI) fs.setIf(ecx&(1<<12) != 0, AVX512BITALG) diff --git a/vendor/github.com/klauspost/cpuid/v2/cpuid_arm64.s b/vendor/github.com/klauspost/cpuid/v2/cpuid_arm64.s index b31d6aec43..b196f78eb4 100644 --- a/vendor/github.com/klauspost/cpuid/v2/cpuid_arm64.s +++ b/vendor/github.com/klauspost/cpuid/v2/cpuid_arm64.s @@ -24,3 +24,13 @@ TEXT ·getInstAttributes(SB), 7, $0 MOVD R1, instAttrReg1+8(FP) RET +TEXT ·getVectorLength(SB), 7, $0 + WORD $0xd2800002 // mov x2, #0 + WORD $0x04225022 // addvl x2, x2, #1 + WORD $0xd37df042 // lsl x2, x2, #3 + WORD $0xd2800003 // mov x3, #0 + WORD $0x04635023 // addpl x3, x3, #1 + WORD $0xd37df063 // lsl x3, x3, #3 + MOVD R2, vl+0(FP) + MOVD R3, pl+8(FP) + RET diff --git a/vendor/github.com/klauspost/cpuid/v2/detect_arm64.go b/vendor/github.com/klauspost/cpuid/v2/detect_arm64.go index 9a53504a04..566743d220 100644 --- a/vendor/github.com/klauspost/cpuid/v2/detect_arm64.go +++ b/vendor/github.com/klauspost/cpuid/v2/detect_arm64.go @@ -10,6 +10,7 @@ import "runtime" func getMidr() (midr uint64) func getProcFeatures() (procFeatures uint64) func getInstAttributes() (instAttrReg0, instAttrReg1 uint64) +func getVectorLength() (vl, pl uint64) func initCPU() { cpuid = func(uint32) (a, b, c, d uint32) { return 0, 0, 0, 0 } @@ -24,7 +25,7 @@ func addInfo(c *CPUInfo, safe bool) { detectOS(c) // ARM64 disabled since it may crash if interrupt is not intercepted by OS. - if safe && !c.Supports(ARMCPUID) && runtime.GOOS != "freebsd" { + if safe && !c.Has(ARMCPUID) && runtime.GOOS != "freebsd" { return } midr := getMidr() diff --git a/vendor/github.com/klauspost/cpuid/v2/detect_ref.go b/vendor/github.com/klauspost/cpuid/v2/detect_ref.go index 9636c2bc17..574f9389c0 100644 --- a/vendor/github.com/klauspost/cpuid/v2/detect_ref.go +++ b/vendor/github.com/klauspost/cpuid/v2/detect_ref.go @@ -10,6 +10,8 @@ func initCPU() { cpuidex = func(x, y uint32) (a, b, c, d uint32) { return 0, 0, 0, 0 } xgetbv = func(uint32) (a, b uint32) { return 0, 0 } rdtscpAsm = func() (a, b, c, d uint32) { return 0, 0, 0, 0 } + } func addInfo(info *CPUInfo, safe bool) {} +func getVectorLength() (vl, pl uint64) { return 0, 0 } diff --git a/vendor/github.com/klauspost/cpuid/v2/detect_x86.go b/vendor/github.com/klauspost/cpuid/v2/detect_x86.go index 799b400c2e..f924c9d839 100644 --- a/vendor/github.com/klauspost/cpuid/v2/detect_x86.go +++ b/vendor/github.com/klauspost/cpuid/v2/detect_x86.go @@ -32,7 +32,10 @@ func addInfo(c *CPUInfo, safe bool) { c.LogicalCores = logicalCores() c.PhysicalCores = physicalCores() c.VendorID, c.VendorString = vendorID() + c.HypervisorVendorID, c.HypervisorVendorString = hypervisorVendorID() c.AVX10Level = c.supportAVX10() c.cacheSize() c.frequencies() } + +func getVectorLength() (vl, pl uint64) { return 0, 0 } diff --git a/vendor/github.com/klauspost/cpuid/v2/featureid_string.go b/vendor/github.com/klauspost/cpuid/v2/featureid_string.go index 3a25603103..e7f874a7e8 100644 --- a/vendor/github.com/klauspost/cpuid/v2/featureid_string.go +++ b/vendor/github.com/klauspost/cpuid/v2/featureid_string.go @@ -15,224 +15,225 @@ func _() { _ = x[AMXBF16-5] _ = x[AMXFP16-6] _ = x[AMXINT8-7] - _ = x[AMXTILE-8] - _ = x[APX_F-9] - _ = x[AVX-10] - _ = x[AVX10-11] - _ = x[AVX10_128-12] - _ = x[AVX10_256-13] - _ = x[AVX10_512-14] - _ = x[AVX2-15] - _ = x[AVX512BF16-16] - _ = x[AVX512BITALG-17] - _ = x[AVX512BW-18] - _ = x[AVX512CD-19] - _ = x[AVX512DQ-20] - _ = x[AVX512ER-21] - _ = x[AVX512F-22] - _ = x[AVX512FP16-23] - _ = x[AVX512IFMA-24] - _ = x[AVX512PF-25] - _ = x[AVX512VBMI-26] - _ = x[AVX512VBMI2-27] - _ = x[AVX512VL-28] - _ = x[AVX512VNNI-29] - _ = x[AVX512VP2INTERSECT-30] - _ = x[AVX512VPOPCNTDQ-31] - _ = x[AVXIFMA-32] - _ = x[AVXNECONVERT-33] - _ = x[AVXSLOW-34] - _ = x[AVXVNNI-35] - _ = x[AVXVNNIINT8-36] - _ = x[AVXVNNIINT16-37] - _ = x[BHI_CTRL-38] - _ = x[BMI1-39] - _ = x[BMI2-40] - _ = x[CETIBT-41] - _ = x[CETSS-42] - _ = x[CLDEMOTE-43] - _ = x[CLMUL-44] - _ = x[CLZERO-45] - _ = x[CMOV-46] - _ = x[CMPCCXADD-47] - _ = x[CMPSB_SCADBS_SHORT-48] - _ = x[CMPXCHG8-49] - _ = x[CPBOOST-50] - _ = x[CPPC-51] - _ = x[CX16-52] - _ = x[EFER_LMSLE_UNS-53] - _ = x[ENQCMD-54] - _ = x[ERMS-55] - _ = x[F16C-56] - _ = x[FLUSH_L1D-57] - _ = x[FMA3-58] - _ = x[FMA4-59] - _ = x[FP128-60] - _ = x[FP256-61] - _ = x[FSRM-62] - _ = x[FXSR-63] - _ = x[FXSROPT-64] - _ = x[GFNI-65] - _ = x[HLE-66] - _ = x[HRESET-67] - _ = x[HTT-68] - _ = x[HWA-69] - _ = x[HYBRID_CPU-70] - _ = x[HYPERVISOR-71] - _ = x[IA32_ARCH_CAP-72] - _ = x[IA32_CORE_CAP-73] - _ = x[IBPB-74] - _ = x[IBPB_BRTYPE-75] - _ = x[IBRS-76] - _ = x[IBRS_PREFERRED-77] - _ = x[IBRS_PROVIDES_SMP-78] - _ = x[IBS-79] - _ = x[IBSBRNTRGT-80] - _ = x[IBSFETCHSAM-81] - _ = x[IBSFFV-82] - _ = x[IBSOPCNT-83] - _ = x[IBSOPCNTEXT-84] - _ = x[IBSOPSAM-85] - _ = x[IBSRDWROPCNT-86] - _ = x[IBSRIPINVALIDCHK-87] - _ = x[IBS_FETCH_CTLX-88] - _ = x[IBS_OPDATA4-89] - _ = x[IBS_OPFUSE-90] - _ = x[IBS_PREVENTHOST-91] - _ = x[IBS_ZEN4-92] - _ = x[IDPRED_CTRL-93] - _ = x[INT_WBINVD-94] - _ = x[INVLPGB-95] - _ = x[KEYLOCKER-96] - _ = x[KEYLOCKERW-97] - _ = x[LAHF-98] - _ = x[LAM-99] - _ = x[LBRVIRT-100] - _ = x[LZCNT-101] - _ = x[MCAOVERFLOW-102] - _ = x[MCDT_NO-103] - _ = x[MCOMMIT-104] - _ = x[MD_CLEAR-105] - _ = x[MMX-106] - _ = x[MMXEXT-107] - _ = x[MOVBE-108] - _ = x[MOVDIR64B-109] - _ = x[MOVDIRI-110] - _ = x[MOVSB_ZL-111] - _ = x[MOVU-112] - _ = x[MPX-113] - _ = x[MSRIRC-114] - _ = x[MSRLIST-115] - _ = x[MSR_PAGEFLUSH-116] - _ = x[NRIPS-117] - _ = x[NX-118] - _ = x[OSXSAVE-119] - _ = x[PCONFIG-120] - _ = x[POPCNT-121] - _ = x[PPIN-122] - _ = x[PREFETCHI-123] - _ = x[PSFD-124] - _ = x[RDPRU-125] - _ = x[RDRAND-126] - _ = x[RDSEED-127] - _ = x[RDTSCP-128] - _ = x[RRSBA_CTRL-129] - _ = x[RTM-130] - _ = x[RTM_ALWAYS_ABORT-131] - _ = x[SBPB-132] - _ = x[SERIALIZE-133] - _ = x[SEV-134] - _ = x[SEV_64BIT-135] - _ = x[SEV_ALTERNATIVE-136] - _ = x[SEV_DEBUGSWAP-137] - _ = x[SEV_ES-138] - _ = x[SEV_RESTRICTED-139] - _ = x[SEV_SNP-140] - _ = x[SGX-141] - _ = x[SGXLC-142] - _ = x[SHA-143] - _ = x[SME-144] - _ = x[SME_COHERENT-145] - _ = x[SPEC_CTRL_SSBD-146] - _ = x[SRBDS_CTRL-147] - _ = x[SRSO_MSR_FIX-148] - _ = x[SRSO_NO-149] - _ = x[SRSO_USER_KERNEL_NO-150] - _ = x[SSE-151] - _ = x[SSE2-152] - _ = x[SSE3-153] - _ = x[SSE4-154] - _ = x[SSE42-155] - _ = x[SSE4A-156] - _ = x[SSSE3-157] - _ = x[STIBP-158] - _ = x[STIBP_ALWAYSON-159] - _ = x[STOSB_SHORT-160] - _ = x[SUCCOR-161] - _ = x[SVM-162] - _ = x[SVMDA-163] - _ = x[SVMFBASID-164] - _ = x[SVML-165] - _ = x[SVMNP-166] - _ = x[SVMPF-167] - _ = x[SVMPFT-168] - _ = x[SYSCALL-169] - _ = x[SYSEE-170] - _ = x[TBM-171] - _ = x[TDX_GUEST-172] - _ = x[TLB_FLUSH_NESTED-173] - _ = x[TME-174] - _ = x[TOPEXT-175] - _ = x[TSCRATEMSR-176] - _ = x[TSXLDTRK-177] - _ = x[VAES-178] - _ = x[VMCBCLEAN-179] - _ = x[VMPL-180] - _ = x[VMSA_REGPROT-181] - _ = x[VMX-182] - _ = x[VPCLMULQDQ-183] - _ = x[VTE-184] - _ = x[WAITPKG-185] - _ = x[WBNOINVD-186] - _ = x[WRMSRNS-187] - _ = x[X87-188] - _ = x[XGETBV1-189] - _ = x[XOP-190] - _ = x[XSAVE-191] - _ = x[XSAVEC-192] - _ = x[XSAVEOPT-193] - _ = x[XSAVES-194] - _ = x[AESARM-195] - _ = x[ARMCPUID-196] - _ = x[ASIMD-197] - _ = x[ASIMDDP-198] - _ = x[ASIMDHP-199] - _ = x[ASIMDRDM-200] - _ = x[ATOMICS-201] - _ = x[CRC32-202] - _ = x[DCPOP-203] - _ = x[EVTSTRM-204] - _ = x[FCMA-205] - _ = x[FP-206] - _ = x[FPHP-207] - _ = x[GPA-208] - _ = x[JSCVT-209] - _ = x[LRCPC-210] - _ = x[PMULL-211] - _ = x[SHA1-212] - _ = x[SHA2-213] - _ = x[SHA3-214] - _ = x[SHA512-215] - _ = x[SM3-216] - _ = x[SM4-217] - _ = x[SVE-218] - _ = x[lastID-219] + _ = x[AMXFP8-8] + _ = x[AMXTILE-9] + _ = x[APX_F-10] + _ = x[AVX-11] + _ = x[AVX10-12] + _ = x[AVX10_128-13] + _ = x[AVX10_256-14] + _ = x[AVX10_512-15] + _ = x[AVX2-16] + _ = x[AVX512BF16-17] + _ = x[AVX512BITALG-18] + _ = x[AVX512BW-19] + _ = x[AVX512CD-20] + _ = x[AVX512DQ-21] + _ = x[AVX512ER-22] + _ = x[AVX512F-23] + _ = x[AVX512FP16-24] + _ = x[AVX512IFMA-25] + _ = x[AVX512PF-26] + _ = x[AVX512VBMI-27] + _ = x[AVX512VBMI2-28] + _ = x[AVX512VL-29] + _ = x[AVX512VNNI-30] + _ = x[AVX512VP2INTERSECT-31] + _ = x[AVX512VPOPCNTDQ-32] + _ = x[AVXIFMA-33] + _ = x[AVXNECONVERT-34] + _ = x[AVXSLOW-35] + _ = x[AVXVNNI-36] + _ = x[AVXVNNIINT8-37] + _ = x[AVXVNNIINT16-38] + _ = x[BHI_CTRL-39] + _ = x[BMI1-40] + _ = x[BMI2-41] + _ = x[CETIBT-42] + _ = x[CETSS-43] + _ = x[CLDEMOTE-44] + _ = x[CLMUL-45] + _ = x[CLZERO-46] + _ = x[CMOV-47] + _ = x[CMPCCXADD-48] + _ = x[CMPSB_SCADBS_SHORT-49] + _ = x[CMPXCHG8-50] + _ = x[CPBOOST-51] + _ = x[CPPC-52] + _ = x[CX16-53] + _ = x[EFER_LMSLE_UNS-54] + _ = x[ENQCMD-55] + _ = x[ERMS-56] + _ = x[F16C-57] + _ = x[FLUSH_L1D-58] + _ = x[FMA3-59] + _ = x[FMA4-60] + _ = x[FP128-61] + _ = x[FP256-62] + _ = x[FSRM-63] + _ = x[FXSR-64] + _ = x[FXSROPT-65] + _ = x[GFNI-66] + _ = x[HLE-67] + _ = x[HRESET-68] + _ = x[HTT-69] + _ = x[HWA-70] + _ = x[HYBRID_CPU-71] + _ = x[HYPERVISOR-72] + _ = x[IA32_ARCH_CAP-73] + _ = x[IA32_CORE_CAP-74] + _ = x[IBPB-75] + _ = x[IBPB_BRTYPE-76] + _ = x[IBRS-77] + _ = x[IBRS_PREFERRED-78] + _ = x[IBRS_PROVIDES_SMP-79] + _ = x[IBS-80] + _ = x[IBSBRNTRGT-81] + _ = x[IBSFETCHSAM-82] + _ = x[IBSFFV-83] + _ = x[IBSOPCNT-84] + _ = x[IBSOPCNTEXT-85] + _ = x[IBSOPSAM-86] + _ = x[IBSRDWROPCNT-87] + _ = x[IBSRIPINVALIDCHK-88] + _ = x[IBS_FETCH_CTLX-89] + _ = x[IBS_OPDATA4-90] + _ = x[IBS_OPFUSE-91] + _ = x[IBS_PREVENTHOST-92] + _ = x[IBS_ZEN4-93] + _ = x[IDPRED_CTRL-94] + _ = x[INT_WBINVD-95] + _ = x[INVLPGB-96] + _ = x[KEYLOCKER-97] + _ = x[KEYLOCKERW-98] + _ = x[LAHF-99] + _ = x[LAM-100] + _ = x[LBRVIRT-101] + _ = x[LZCNT-102] + _ = x[MCAOVERFLOW-103] + _ = x[MCDT_NO-104] + _ = x[MCOMMIT-105] + _ = x[MD_CLEAR-106] + _ = x[MMX-107] + _ = x[MMXEXT-108] + _ = x[MOVBE-109] + _ = x[MOVDIR64B-110] + _ = x[MOVDIRI-111] + _ = x[MOVSB_ZL-112] + _ = x[MOVU-113] + _ = x[MPX-114] + _ = x[MSRIRC-115] + _ = x[MSRLIST-116] + _ = x[MSR_PAGEFLUSH-117] + _ = x[NRIPS-118] + _ = x[NX-119] + _ = x[OSXSAVE-120] + _ = x[PCONFIG-121] + _ = x[POPCNT-122] + _ = x[PPIN-123] + _ = x[PREFETCHI-124] + _ = x[PSFD-125] + _ = x[RDPRU-126] + _ = x[RDRAND-127] + _ = x[RDSEED-128] + _ = x[RDTSCP-129] + _ = x[RRSBA_CTRL-130] + _ = x[RTM-131] + _ = x[RTM_ALWAYS_ABORT-132] + _ = x[SBPB-133] + _ = x[SERIALIZE-134] + _ = x[SEV-135] + _ = x[SEV_64BIT-136] + _ = x[SEV_ALTERNATIVE-137] + _ = x[SEV_DEBUGSWAP-138] + _ = x[SEV_ES-139] + _ = x[SEV_RESTRICTED-140] + _ = x[SEV_SNP-141] + _ = x[SGX-142] + _ = x[SGXLC-143] + _ = x[SHA-144] + _ = x[SME-145] + _ = x[SME_COHERENT-146] + _ = x[SPEC_CTRL_SSBD-147] + _ = x[SRBDS_CTRL-148] + _ = x[SRSO_MSR_FIX-149] + _ = x[SRSO_NO-150] + _ = x[SRSO_USER_KERNEL_NO-151] + _ = x[SSE-152] + _ = x[SSE2-153] + _ = x[SSE3-154] + _ = x[SSE4-155] + _ = x[SSE42-156] + _ = x[SSE4A-157] + _ = x[SSSE3-158] + _ = x[STIBP-159] + _ = x[STIBP_ALWAYSON-160] + _ = x[STOSB_SHORT-161] + _ = x[SUCCOR-162] + _ = x[SVM-163] + _ = x[SVMDA-164] + _ = x[SVMFBASID-165] + _ = x[SVML-166] + _ = x[SVMNP-167] + _ = x[SVMPF-168] + _ = x[SVMPFT-169] + _ = x[SYSCALL-170] + _ = x[SYSEE-171] + _ = x[TBM-172] + _ = x[TDX_GUEST-173] + _ = x[TLB_FLUSH_NESTED-174] + _ = x[TME-175] + _ = x[TOPEXT-176] + _ = x[TSCRATEMSR-177] + _ = x[TSXLDTRK-178] + _ = x[VAES-179] + _ = x[VMCBCLEAN-180] + _ = x[VMPL-181] + _ = x[VMSA_REGPROT-182] + _ = x[VMX-183] + _ = x[VPCLMULQDQ-184] + _ = x[VTE-185] + _ = x[WAITPKG-186] + _ = x[WBNOINVD-187] + _ = x[WRMSRNS-188] + _ = x[X87-189] + _ = x[XGETBV1-190] + _ = x[XOP-191] + _ = x[XSAVE-192] + _ = x[XSAVEC-193] + _ = x[XSAVEOPT-194] + _ = x[XSAVES-195] + _ = x[AESARM-196] + _ = x[ARMCPUID-197] + _ = x[ASIMD-198] + _ = x[ASIMDDP-199] + _ = x[ASIMDHP-200] + _ = x[ASIMDRDM-201] + _ = x[ATOMICS-202] + _ = x[CRC32-203] + _ = x[DCPOP-204] + _ = x[EVTSTRM-205] + _ = x[FCMA-206] + _ = x[FP-207] + _ = x[FPHP-208] + _ = x[GPA-209] + _ = x[JSCVT-210] + _ = x[LRCPC-211] + _ = x[PMULL-212] + _ = x[SHA1-213] + _ = x[SHA2-214] + _ = x[SHA3-215] + _ = x[SHA512-216] + _ = x[SM3-217] + _ = x[SM4-218] + _ = x[SVE-219] + _ = x[lastID-220] _ = x[firstID-0] } -const _FeatureID_name = "firstIDADXAESNIAMD3DNOWAMD3DNOWEXTAMXBF16AMXFP16AMXINT8AMXTILEAPX_FAVXAVX10AVX10_128AVX10_256AVX10_512AVX2AVX512BF16AVX512BITALGAVX512BWAVX512CDAVX512DQAVX512ERAVX512FAVX512FP16AVX512IFMAAVX512PFAVX512VBMIAVX512VBMI2AVX512VLAVX512VNNIAVX512VP2INTERSECTAVX512VPOPCNTDQAVXIFMAAVXNECONVERTAVXSLOWAVXVNNIAVXVNNIINT8AVXVNNIINT16BHI_CTRLBMI1BMI2CETIBTCETSSCLDEMOTECLMULCLZEROCMOVCMPCCXADDCMPSB_SCADBS_SHORTCMPXCHG8CPBOOSTCPPCCX16EFER_LMSLE_UNSENQCMDERMSF16CFLUSH_L1DFMA3FMA4FP128FP256FSRMFXSRFXSROPTGFNIHLEHRESETHTTHWAHYBRID_CPUHYPERVISORIA32_ARCH_CAPIA32_CORE_CAPIBPBIBPB_BRTYPEIBRSIBRS_PREFERREDIBRS_PROVIDES_SMPIBSIBSBRNTRGTIBSFETCHSAMIBSFFVIBSOPCNTIBSOPCNTEXTIBSOPSAMIBSRDWROPCNTIBSRIPINVALIDCHKIBS_FETCH_CTLXIBS_OPDATA4IBS_OPFUSEIBS_PREVENTHOSTIBS_ZEN4IDPRED_CTRLINT_WBINVDINVLPGBKEYLOCKERKEYLOCKERWLAHFLAMLBRVIRTLZCNTMCAOVERFLOWMCDT_NOMCOMMITMD_CLEARMMXMMXEXTMOVBEMOVDIR64BMOVDIRIMOVSB_ZLMOVUMPXMSRIRCMSRLISTMSR_PAGEFLUSHNRIPSNXOSXSAVEPCONFIGPOPCNTPPINPREFETCHIPSFDRDPRURDRANDRDSEEDRDTSCPRRSBA_CTRLRTMRTM_ALWAYS_ABORTSBPBSERIALIZESEVSEV_64BITSEV_ALTERNATIVESEV_DEBUGSWAPSEV_ESSEV_RESTRICTEDSEV_SNPSGXSGXLCSHASMESME_COHERENTSPEC_CTRL_SSBDSRBDS_CTRLSRSO_MSR_FIXSRSO_NOSRSO_USER_KERNEL_NOSSESSE2SSE3SSE4SSE42SSE4ASSSE3STIBPSTIBP_ALWAYSONSTOSB_SHORTSUCCORSVMSVMDASVMFBASIDSVMLSVMNPSVMPFSVMPFTSYSCALLSYSEETBMTDX_GUESTTLB_FLUSH_NESTEDTMETOPEXTTSCRATEMSRTSXLDTRKVAESVMCBCLEANVMPLVMSA_REGPROTVMXVPCLMULQDQVTEWAITPKGWBNOINVDWRMSRNSX87XGETBV1XOPXSAVEXSAVECXSAVEOPTXSAVESAESARMARMCPUIDASIMDASIMDDPASIMDHPASIMDRDMATOMICSCRC32DCPOPEVTSTRMFCMAFPFPHPGPAJSCVTLRCPCPMULLSHA1SHA2SHA3SHA512SM3SM4SVElastID" +const _FeatureID_name = "firstIDADXAESNIAMD3DNOWAMD3DNOWEXTAMXBF16AMXFP16AMXINT8AMXFP8AMXTILEAPX_FAVXAVX10AVX10_128AVX10_256AVX10_512AVX2AVX512BF16AVX512BITALGAVX512BWAVX512CDAVX512DQAVX512ERAVX512FAVX512FP16AVX512IFMAAVX512PFAVX512VBMIAVX512VBMI2AVX512VLAVX512VNNIAVX512VP2INTERSECTAVX512VPOPCNTDQAVXIFMAAVXNECONVERTAVXSLOWAVXVNNIAVXVNNIINT8AVXVNNIINT16BHI_CTRLBMI1BMI2CETIBTCETSSCLDEMOTECLMULCLZEROCMOVCMPCCXADDCMPSB_SCADBS_SHORTCMPXCHG8CPBOOSTCPPCCX16EFER_LMSLE_UNSENQCMDERMSF16CFLUSH_L1DFMA3FMA4FP128FP256FSRMFXSRFXSROPTGFNIHLEHRESETHTTHWAHYBRID_CPUHYPERVISORIA32_ARCH_CAPIA32_CORE_CAPIBPBIBPB_BRTYPEIBRSIBRS_PREFERREDIBRS_PROVIDES_SMPIBSIBSBRNTRGTIBSFETCHSAMIBSFFVIBSOPCNTIBSOPCNTEXTIBSOPSAMIBSRDWROPCNTIBSRIPINVALIDCHKIBS_FETCH_CTLXIBS_OPDATA4IBS_OPFUSEIBS_PREVENTHOSTIBS_ZEN4IDPRED_CTRLINT_WBINVDINVLPGBKEYLOCKERKEYLOCKERWLAHFLAMLBRVIRTLZCNTMCAOVERFLOWMCDT_NOMCOMMITMD_CLEARMMXMMXEXTMOVBEMOVDIR64BMOVDIRIMOVSB_ZLMOVUMPXMSRIRCMSRLISTMSR_PAGEFLUSHNRIPSNXOSXSAVEPCONFIGPOPCNTPPINPREFETCHIPSFDRDPRURDRANDRDSEEDRDTSCPRRSBA_CTRLRTMRTM_ALWAYS_ABORTSBPBSERIALIZESEVSEV_64BITSEV_ALTERNATIVESEV_DEBUGSWAPSEV_ESSEV_RESTRICTEDSEV_SNPSGXSGXLCSHASMESME_COHERENTSPEC_CTRL_SSBDSRBDS_CTRLSRSO_MSR_FIXSRSO_NOSRSO_USER_KERNEL_NOSSESSE2SSE3SSE4SSE42SSE4ASSSE3STIBPSTIBP_ALWAYSONSTOSB_SHORTSUCCORSVMSVMDASVMFBASIDSVMLSVMNPSVMPFSVMPFTSYSCALLSYSEETBMTDX_GUESTTLB_FLUSH_NESTEDTMETOPEXTTSCRATEMSRTSXLDTRKVAESVMCBCLEANVMPLVMSA_REGPROTVMXVPCLMULQDQVTEWAITPKGWBNOINVDWRMSRNSX87XGETBV1XOPXSAVEXSAVECXSAVEOPTXSAVESAESARMARMCPUIDASIMDASIMDDPASIMDHPASIMDRDMATOMICSCRC32DCPOPEVTSTRMFCMAFPFPHPGPAJSCVTLRCPCPMULLSHA1SHA2SHA3SHA512SM3SM4SVElastID" -var _FeatureID_index = [...]uint16{0, 7, 10, 15, 23, 34, 41, 48, 55, 62, 67, 70, 75, 84, 93, 102, 106, 116, 128, 136, 144, 152, 160, 167, 177, 187, 195, 205, 216, 224, 234, 252, 267, 274, 286, 293, 300, 311, 323, 331, 335, 339, 345, 350, 358, 363, 369, 373, 382, 400, 408, 415, 419, 423, 437, 443, 447, 451, 460, 464, 468, 473, 478, 482, 486, 493, 497, 500, 506, 509, 512, 522, 532, 545, 558, 562, 573, 577, 591, 608, 611, 621, 632, 638, 646, 657, 665, 677, 693, 707, 718, 728, 743, 751, 762, 772, 779, 788, 798, 802, 805, 812, 817, 828, 835, 842, 850, 853, 859, 864, 873, 880, 888, 892, 895, 901, 908, 921, 926, 928, 935, 942, 948, 952, 961, 965, 970, 976, 982, 988, 998, 1001, 1017, 1021, 1030, 1033, 1042, 1057, 1070, 1076, 1090, 1097, 1100, 1105, 1108, 1111, 1123, 1137, 1147, 1159, 1166, 1185, 1188, 1192, 1196, 1200, 1205, 1210, 1215, 1220, 1234, 1245, 1251, 1254, 1259, 1268, 1272, 1277, 1282, 1288, 1295, 1300, 1303, 1312, 1328, 1331, 1337, 1347, 1355, 1359, 1368, 1372, 1384, 1387, 1397, 1400, 1407, 1415, 1422, 1425, 1432, 1435, 1440, 1446, 1454, 1460, 1466, 1474, 1479, 1486, 1493, 1501, 1508, 1513, 1518, 1525, 1529, 1531, 1535, 1538, 1543, 1548, 1553, 1557, 1561, 1565, 1571, 1574, 1577, 1580, 1586} +var _FeatureID_index = [...]uint16{0, 7, 10, 15, 23, 34, 41, 48, 55, 61, 68, 73, 76, 81, 90, 99, 108, 112, 122, 134, 142, 150, 158, 166, 173, 183, 193, 201, 211, 222, 230, 240, 258, 273, 280, 292, 299, 306, 317, 329, 337, 341, 345, 351, 356, 364, 369, 375, 379, 388, 406, 414, 421, 425, 429, 443, 449, 453, 457, 466, 470, 474, 479, 484, 488, 492, 499, 503, 506, 512, 515, 518, 528, 538, 551, 564, 568, 579, 583, 597, 614, 617, 627, 638, 644, 652, 663, 671, 683, 699, 713, 724, 734, 749, 757, 768, 778, 785, 794, 804, 808, 811, 818, 823, 834, 841, 848, 856, 859, 865, 870, 879, 886, 894, 898, 901, 907, 914, 927, 932, 934, 941, 948, 954, 958, 967, 971, 976, 982, 988, 994, 1004, 1007, 1023, 1027, 1036, 1039, 1048, 1063, 1076, 1082, 1096, 1103, 1106, 1111, 1114, 1117, 1129, 1143, 1153, 1165, 1172, 1191, 1194, 1198, 1202, 1206, 1211, 1216, 1221, 1226, 1240, 1251, 1257, 1260, 1265, 1274, 1278, 1283, 1288, 1294, 1301, 1306, 1309, 1318, 1334, 1337, 1343, 1353, 1361, 1365, 1374, 1378, 1390, 1393, 1403, 1406, 1413, 1421, 1428, 1431, 1438, 1441, 1446, 1452, 1460, 1466, 1472, 1480, 1485, 1492, 1499, 1507, 1514, 1519, 1524, 1531, 1535, 1537, 1541, 1544, 1549, 1554, 1559, 1563, 1567, 1571, 1577, 1580, 1583, 1586, 1592} func (i FeatureID) String() string { if i < 0 || i >= FeatureID(len(_FeatureID_index)-1) { @@ -270,12 +271,17 @@ func _() { _ = x[AMCC-23] _ = x[Qualcomm-24] _ = x[Marvell-25] - _ = x[lastVendor-26] + _ = x[QEMU-26] + _ = x[QNX-27] + _ = x[ACRN-28] + _ = x[SRE-29] + _ = x[Apple-30] + _ = x[lastVendor-31] } -const _Vendor_name = "VendorUnknownIntelAMDVIATransmetaNSCKVMMSVMVMwareXenHVMBhyveHygonSiSRDCAmpereARMBroadcomCaviumDECFujitsuInfineonMotorolaNVIDIAAMCCQualcommMarvelllastVendor" +const _Vendor_name = "VendorUnknownIntelAMDVIATransmetaNSCKVMMSVMVMwareXenHVMBhyveHygonSiSRDCAmpereARMBroadcomCaviumDECFujitsuInfineonMotorolaNVIDIAAMCCQualcommMarvellQEMUQNXACRNSREApplelastVendor" -var _Vendor_index = [...]uint8{0, 13, 18, 21, 24, 33, 36, 39, 43, 49, 55, 60, 65, 68, 71, 77, 80, 88, 94, 97, 104, 112, 120, 126, 130, 138, 145, 155} +var _Vendor_index = [...]uint8{0, 13, 18, 21, 24, 33, 36, 39, 43, 49, 55, 60, 65, 68, 71, 77, 80, 88, 94, 97, 104, 112, 120, 126, 130, 138, 145, 149, 152, 156, 159, 164, 174} func (i Vendor) String() string { if i < 0 || i >= Vendor(len(_Vendor_index)-1) { diff --git a/vendor/github.com/minio/minio-go/v7/api-copy-object.go b/vendor/github.com/minio/minio-go/v7/api-copy-object.go index 0c95d91ec7..b6cadc86a9 100644 --- a/vendor/github.com/minio/minio-go/v7/api-copy-object.go +++ b/vendor/github.com/minio/minio-go/v7/api-copy-object.go @@ -68,7 +68,7 @@ func (c *Client) CopyObject(ctx context.Context, dst CopyDestOptions, src CopySr Bucket: dst.Bucket, Key: dst.Object, LastModified: cpObjRes.LastModified, - ETag: trimEtag(resp.Header.Get("ETag")), + ETag: trimEtag(cpObjRes.ETag), VersionID: resp.Header.Get(amzVersionID), Expiration: expTime, ExpirationRuleID: ruleID, diff --git a/vendor/github.com/minio/minio-go/v7/api-presigned.go b/vendor/github.com/minio/minio-go/v7/api-presigned.go index 9e85f81816..29642200ee 100644 --- a/vendor/github.com/minio/minio-go/v7/api-presigned.go +++ b/vendor/github.com/minio/minio-go/v7/api-presigned.go @@ -140,7 +140,7 @@ func (c *Client) PresignedPostPolicy(ctx context.Context, p *PostPolicy) (u *url } // Get credentials from the configured credentials provider. - credValues, err := c.credsProvider.Get() + credValues, err := c.credsProvider.GetWithContext(c.CredContext()) if err != nil { return nil, nil, err } diff --git a/vendor/github.com/minio/minio-go/v7/api.go b/vendor/github.com/minio/minio-go/v7/api.go index 83c003e499..cc0ded2c7f 100644 --- a/vendor/github.com/minio/minio-go/v7/api.go +++ b/vendor/github.com/minio/minio-go/v7/api.go @@ -133,7 +133,7 @@ type Options struct { // Global constants. const ( libraryName = "minio-go" - libraryVersion = "v7.0.82" + libraryVersion = "v7.0.84" ) // User Agent should always following the below style. @@ -600,9 +600,9 @@ func (c *Client) executeMethod(ctx context.Context, method string, metadata requ return nil, errors.New(c.endpointURL.String() + " is offline.") } - var retryable bool // Indicates if request can be retried. - var bodySeeker io.Seeker // Extracted seeker from io.Reader. - var reqRetry = c.maxRetries // Indicates how many times we can retry the request + var retryable bool // Indicates if request can be retried. + var bodySeeker io.Seeker // Extracted seeker from io.Reader. + reqRetry := c.maxRetries // Indicates how many times we can retry the request if metadata.contentBody != nil { // Check if body is seekable then it is retryable. @@ -808,7 +808,7 @@ func (c *Client) newRequest(ctx context.Context, method string, metadata request } // Get credentials from the configured credentials provider. - value, err := c.credsProvider.Get() + value, err := c.credsProvider.GetWithContext(c.CredContext()) if err != nil { return nil, err } @@ -1018,3 +1018,15 @@ func (c *Client) isVirtualHostStyleRequest(url url.URL, bucketName string) bool // path style requests return s3utils.IsVirtualHostSupported(url, bucketName) } + +// CredContext returns the context for fetching credentials +func (c *Client) CredContext() *credentials.CredContext { + httpClient := c.httpClient + if httpClient == nil { + httpClient = http.DefaultClient + } + return &credentials.CredContext{ + Client: httpClient, + Endpoint: c.endpointURL.String(), + } +} diff --git a/vendor/github.com/minio/minio-go/v7/bucket-cache.go b/vendor/github.com/minio/minio-go/v7/bucket-cache.go index b1d3b3852c..4e4305acd5 100644 --- a/vendor/github.com/minio/minio-go/v7/bucket-cache.go +++ b/vendor/github.com/minio/minio-go/v7/bucket-cache.go @@ -212,7 +212,7 @@ func (c *Client) getBucketLocationRequest(ctx context.Context, bucketName string c.setUserAgent(req) // Get credentials from the configured credentials provider. - value, err := c.credsProvider.Get() + value, err := c.credsProvider.GetWithContext(c.CredContext()) if err != nil { return nil, err } diff --git a/vendor/github.com/minio/minio-go/v7/pkg/credentials/assume_role.go b/vendor/github.com/minio/minio-go/v7/pkg/credentials/assume_role.go index d245bc07a3..cd0a641bde 100644 --- a/vendor/github.com/minio/minio-go/v7/pkg/credentials/assume_role.go +++ b/vendor/github.com/minio/minio-go/v7/pkg/credentials/assume_role.go @@ -76,7 +76,8 @@ type AssumeRoleResult struct { type STSAssumeRole struct { Expiry - // Required http Client to use when connecting to MinIO STS service. + // Optional http Client to use when connecting to MinIO STS service + // (overrides default client in CredContext) Client *http.Client // STS endpoint to fetch STS credentials. @@ -108,16 +109,10 @@ type STSAssumeRoleOptions struct { // NewSTSAssumeRole returns a pointer to a new // Credentials object wrapping the STSAssumeRole. func NewSTSAssumeRole(stsEndpoint string, opts STSAssumeRoleOptions) (*Credentials, error) { - if stsEndpoint == "" { - return nil, errors.New("STS endpoint cannot be empty") - } if opts.AccessKey == "" || opts.SecretKey == "" { return nil, errors.New("AssumeRole credentials access/secretkey is mandatory") } return New(&STSAssumeRole{ - Client: &http.Client{ - Transport: http.DefaultTransport, - }, STSEndpoint: stsEndpoint, Options: opts, }), nil @@ -222,10 +217,30 @@ func getAssumeRoleCredentials(clnt *http.Client, endpoint string, opts STSAssume return a, nil } -// Retrieve retrieves credentials from the MinIO service. -// Error will be returned if the request fails. -func (m *STSAssumeRole) Retrieve() (Value, error) { - a, err := getAssumeRoleCredentials(m.Client, m.STSEndpoint, m.Options) +// RetrieveWithCredContext retrieves credentials from the MinIO service. +// Error will be returned if the request fails, optional cred context. +func (m *STSAssumeRole) RetrieveWithCredContext(cc *CredContext) (Value, error) { + if cc == nil { + cc = defaultCredContext + } + + client := m.Client + if client == nil { + client = cc.Client + } + if client == nil { + client = defaultCredContext.Client + } + + stsEndpoint := m.STSEndpoint + if stsEndpoint == "" { + stsEndpoint = cc.Endpoint + } + if stsEndpoint == "" { + return Value{}, errors.New("STS endpoint unknown") + } + + a, err := getAssumeRoleCredentials(client, stsEndpoint, m.Options) if err != nil { return Value{}, err } @@ -241,3 +256,9 @@ func (m *STSAssumeRole) Retrieve() (Value, error) { SignerType: SignatureV4, }, nil } + +// Retrieve retrieves credentials from the MinIO service. +// Error will be returned if the request fails. +func (m *STSAssumeRole) Retrieve() (Value, error) { + return m.RetrieveWithCredContext(nil) +} diff --git a/vendor/github.com/minio/minio-go/v7/pkg/credentials/chain.go b/vendor/github.com/minio/minio-go/v7/pkg/credentials/chain.go index ddccfb173f..5ef3597d10 100644 --- a/vendor/github.com/minio/minio-go/v7/pkg/credentials/chain.go +++ b/vendor/github.com/minio/minio-go/v7/pkg/credentials/chain.go @@ -55,6 +55,24 @@ func NewChainCredentials(providers []Provider) *Credentials { }) } +// RetrieveWithCredContext is like Retrieve with CredContext +func (c *Chain) RetrieveWithCredContext(cc *CredContext) (Value, error) { + for _, p := range c.Providers { + creds, _ := p.RetrieveWithCredContext(cc) + // Always prioritize non-anonymous providers, if any. + if creds.AccessKeyID == "" && creds.SecretAccessKey == "" { + continue + } + c.curr = p + return creds, nil + } + // At this point we have exhausted all the providers and + // are left without any credentials return anonymous. + return Value{ + SignerType: SignatureAnonymous, + }, nil +} + // Retrieve returns the credentials value, returns no credentials(anonymous) // if no credentials provider returned any value. // diff --git a/vendor/github.com/minio/minio-go/v7/pkg/credentials/credentials.go b/vendor/github.com/minio/minio-go/v7/pkg/credentials/credentials.go index 68f9b38157..52aff9a57f 100644 --- a/vendor/github.com/minio/minio-go/v7/pkg/credentials/credentials.go +++ b/vendor/github.com/minio/minio-go/v7/pkg/credentials/credentials.go @@ -18,6 +18,7 @@ package credentials import ( + "net/http" "sync" "time" ) @@ -30,6 +31,10 @@ const ( defaultExpiryWindow = 0.8 ) +// defaultCredContext is used when the credential context doesn't +// actually matter or the default context is suitable. +var defaultCredContext = &CredContext{Client: http.DefaultClient} + // A Value is the S3 credentials value for individual credential fields. type Value struct { // S3 Access key ID @@ -52,8 +57,17 @@ type Value struct { // Value. A provider is required to manage its own Expired state, and what to // be expired means. type Provider interface { + // RetrieveWithCredContext returns nil if it successfully retrieved the + // value. Error is returned if the value were not obtainable, or empty. + // optionally takes CredContext for additional context to retrieve credentials. + RetrieveWithCredContext(cc *CredContext) (Value, error) + // Retrieve returns nil if it successfully retrieved the value. // Error is returned if the value were not obtainable, or empty. + // + // Deprecated: Retrieve() exists for historical compatibility and should not + // be used. To get new credentials use the RetrieveWithCredContext function + // to ensure the proper context (i.e. HTTP client) will be used. Retrieve() (Value, error) // IsExpired returns if the credentials are no longer valid, and need @@ -61,6 +75,18 @@ type Provider interface { IsExpired() bool } +// CredContext is passed to the Retrieve function of a provider to provide +// some additional context to retrieve credentials. +type CredContext struct { + // Client specifies the HTTP client that should be used if an HTTP + // request is to be made to fetch the credentials. + Client *http.Client + + // Endpoint specifies the MinIO endpoint that will be used if no + // explicit endpoint is provided. + Endpoint string +} + // A Expiry provides shared expiration logic to be used by credentials // providers to implement expiry functionality. // @@ -146,16 +172,36 @@ func New(provider Provider) *Credentials { // // If Credentials.Expire() was called the credentials Value will be force // expired, and the next call to Get() will cause them to be refreshed. +// +// Deprecated: Get() exists for historical compatibility and should not be +// used. To get new credentials use the Credentials.GetWithContext function +// to ensure the proper context (i.e. HTTP client) will be used. func (c *Credentials) Get() (Value, error) { + return c.GetWithContext(nil) +} + +// GetWithContext returns the credentials value, or error if the +// credentials Value failed to be retrieved. +// +// Will return the cached credentials Value if it has not expired. If the +// credentials Value has expired the Provider's Retrieve() will be called +// to refresh the credentials. +// +// If Credentials.Expire() was called the credentials Value will be force +// expired, and the next call to Get() will cause them to be refreshed. +func (c *Credentials) GetWithContext(cc *CredContext) (Value, error) { if c == nil { return Value{}, nil } + if cc == nil { + cc = defaultCredContext + } c.Lock() defer c.Unlock() if c.isExpired() { - creds, err := c.provider.Retrieve() + creds, err := c.provider.RetrieveWithCredContext(cc) if err != nil { return Value{}, err } diff --git a/vendor/github.com/minio/minio-go/v7/pkg/credentials/env_aws.go b/vendor/github.com/minio/minio-go/v7/pkg/credentials/env_aws.go index b6e60d0e16..21ab0a38a4 100644 --- a/vendor/github.com/minio/minio-go/v7/pkg/credentials/env_aws.go +++ b/vendor/github.com/minio/minio-go/v7/pkg/credentials/env_aws.go @@ -37,8 +37,7 @@ func NewEnvAWS() *Credentials { return New(&EnvAWS{}) } -// Retrieve retrieves the keys from the environment. -func (e *EnvAWS) Retrieve() (Value, error) { +func (e *EnvAWS) retrieve() (Value, error) { e.retrieved = false id := os.Getenv("AWS_ACCESS_KEY_ID") @@ -65,6 +64,16 @@ func (e *EnvAWS) Retrieve() (Value, error) { }, nil } +// Retrieve retrieves the keys from the environment. +func (e *EnvAWS) Retrieve() (Value, error) { + return e.retrieve() +} + +// RetrieveWithCredContext is like Retrieve (no-op input of Cred Context) +func (e *EnvAWS) RetrieveWithCredContext(_ *CredContext) (Value, error) { + return e.retrieve() +} + // IsExpired returns if the credentials have been retrieved. func (e *EnvAWS) IsExpired() bool { return !e.retrieved diff --git a/vendor/github.com/minio/minio-go/v7/pkg/credentials/env_minio.go b/vendor/github.com/minio/minio-go/v7/pkg/credentials/env_minio.go index 5bfeab140a..dbfbdfcef1 100644 --- a/vendor/github.com/minio/minio-go/v7/pkg/credentials/env_minio.go +++ b/vendor/github.com/minio/minio-go/v7/pkg/credentials/env_minio.go @@ -38,8 +38,7 @@ func NewEnvMinio() *Credentials { return New(&EnvMinio{}) } -// Retrieve retrieves the keys from the environment. -func (e *EnvMinio) Retrieve() (Value, error) { +func (e *EnvMinio) retrieve() (Value, error) { e.retrieved = false id := os.Getenv("MINIO_ROOT_USER") @@ -62,6 +61,16 @@ func (e *EnvMinio) Retrieve() (Value, error) { }, nil } +// Retrieve retrieves the keys from the environment. +func (e *EnvMinio) Retrieve() (Value, error) { + return e.retrieve() +} + +// RetrieveWithCredContext is like Retrieve() (no-op input cred context) +func (e *EnvMinio) RetrieveWithCredContext(_ *CredContext) (Value, error) { + return e.retrieve() +} + // IsExpired returns if the credentials have been retrieved. func (e *EnvMinio) IsExpired() bool { return !e.retrieved diff --git a/vendor/github.com/minio/minio-go/v7/pkg/credentials/file_aws_credentials.go b/vendor/github.com/minio/minio-go/v7/pkg/credentials/file_aws_credentials.go index 541e1a72f0..0c83fc7fa4 100644 --- a/vendor/github.com/minio/minio-go/v7/pkg/credentials/file_aws_credentials.go +++ b/vendor/github.com/minio/minio-go/v7/pkg/credentials/file_aws_credentials.go @@ -71,9 +71,7 @@ func NewFileAWSCredentials(filename, profile string) *Credentials { }) } -// Retrieve reads and extracts the shared credentials from the current -// users home directory. -func (p *FileAWSCredentials) Retrieve() (Value, error) { +func (p *FileAWSCredentials) retrieve() (Value, error) { if p.Filename == "" { p.Filename = os.Getenv("AWS_SHARED_CREDENTIALS_FILE") if p.Filename == "" { @@ -142,6 +140,17 @@ func (p *FileAWSCredentials) Retrieve() (Value, error) { }, nil } +// Retrieve reads and extracts the shared credentials from the current +// users home directory. +func (p *FileAWSCredentials) Retrieve() (Value, error) { + return p.retrieve() +} + +// RetrieveWithCredContext is like Retrieve(), cred context is no-op for File credentials +func (p *FileAWSCredentials) RetrieveWithCredContext(_ *CredContext) (Value, error) { + return p.retrieve() +} + // loadProfiles loads from the file pointed to by shared credentials filename for profile. // The credentials retrieved from the profile will be returned or error. Error will be // returned if it fails to read from the file, or the data is invalid. diff --git a/vendor/github.com/minio/minio-go/v7/pkg/credentials/file_minio_client.go b/vendor/github.com/minio/minio-go/v7/pkg/credentials/file_minio_client.go index 750e26ffa8..5805281fe9 100644 --- a/vendor/github.com/minio/minio-go/v7/pkg/credentials/file_minio_client.go +++ b/vendor/github.com/minio/minio-go/v7/pkg/credentials/file_minio_client.go @@ -56,9 +56,7 @@ func NewFileMinioClient(filename, alias string) *Credentials { }) } -// Retrieve reads and extracts the shared credentials from the current -// users home directory. -func (p *FileMinioClient) Retrieve() (Value, error) { +func (p *FileMinioClient) retrieve() (Value, error) { if p.Filename == "" { if value, ok := os.LookupEnv("MINIO_SHARED_CREDENTIALS_FILE"); ok { p.Filename = value @@ -96,6 +94,17 @@ func (p *FileMinioClient) Retrieve() (Value, error) { }, nil } +// Retrieve reads and extracts the shared credentials from the current +// users home directory. +func (p *FileMinioClient) Retrieve() (Value, error) { + return p.retrieve() +} + +// RetrieveWithCredContext - is like Retrieve() +func (p *FileMinioClient) RetrieveWithCredContext(_ *CredContext) (Value, error) { + return p.retrieve() +} + // IsExpired returns if the shared credentials have expired. func (p *FileMinioClient) IsExpired() bool { return !p.retrieved diff --git a/vendor/github.com/minio/minio-go/v7/pkg/credentials/iam_aws.go b/vendor/github.com/minio/minio-go/v7/pkg/credentials/iam_aws.go index ea4b3ef937..e3230bb186 100644 --- a/vendor/github.com/minio/minio-go/v7/pkg/credentials/iam_aws.go +++ b/vendor/github.com/minio/minio-go/v7/pkg/credentials/iam_aws.go @@ -49,7 +49,8 @@ const DefaultExpiryWindow = -1 type IAM struct { Expiry - // Required http Client to use when connecting to IAM metadata service. + // Optional http Client to use when connecting to IAM metadata service + // (overrides default client in CredContext) Client *http.Client // Custom endpoint to fetch IAM role credentials. @@ -90,17 +91,16 @@ const ( // NewIAM returns a pointer to a new Credentials object wrapping the IAM. func NewIAM(endpoint string) *Credentials { return New(&IAM{ - Client: &http.Client{ - Transport: http.DefaultTransport, - }, Endpoint: endpoint, }) } -// Retrieve retrieves credentials from the EC2 service. -// Error will be returned if the request fails, or unable to extract -// the desired -func (m *IAM) Retrieve() (Value, error) { +// RetrieveWithCredContext is like Retrieve with Cred Context +func (m *IAM) RetrieveWithCredContext(cc *CredContext) (Value, error) { + if cc == nil { + cc = defaultCredContext + } + token := os.Getenv("AWS_CONTAINER_AUTHORIZATION_TOKEN") if token == "" { token = m.Container.AuthorizationToken @@ -144,7 +144,16 @@ func (m *IAM) Retrieve() (Value, error) { var roleCreds ec2RoleCredRespBody var err error + client := m.Client + if client == nil { + client = cc.Client + } + if client == nil { + client = defaultCredContext.Client + } + endpoint := m.Endpoint + switch { case identityFile != "": if len(endpoint) == 0 { @@ -160,7 +169,7 @@ func (m *IAM) Retrieve() (Value, error) { } creds := &STSWebIdentity{ - Client: m.Client, + Client: client, STSEndpoint: endpoint, GetWebIDTokenExpiry: func() (*WebIdentityToken, error) { token, err := os.ReadFile(identityFile) @@ -174,7 +183,7 @@ func (m *IAM) Retrieve() (Value, error) { roleSessionName: roleSessionName, } - stsWebIdentityCreds, err := creds.Retrieve() + stsWebIdentityCreds, err := creds.RetrieveWithCredContext(cc) if err == nil { m.SetExpiration(creds.Expiration(), DefaultExpiryWindow) } @@ -185,11 +194,11 @@ func (m *IAM) Retrieve() (Value, error) { endpoint = fmt.Sprintf("%s%s", DefaultECSRoleEndpoint, relativeURI) } - roleCreds, err = getEcsTaskCredentials(m.Client, endpoint, token) + roleCreds, err = getEcsTaskCredentials(client, endpoint, token) case tokenFile != "" && fullURI != "": endpoint = fullURI - roleCreds, err = getEKSPodIdentityCredentials(m.Client, endpoint, tokenFile) + roleCreds, err = getEKSPodIdentityCredentials(client, endpoint, tokenFile) case fullURI != "": if len(endpoint) == 0 { @@ -203,10 +212,10 @@ func (m *IAM) Retrieve() (Value, error) { } } - roleCreds, err = getEcsTaskCredentials(m.Client, endpoint, token) + roleCreds, err = getEcsTaskCredentials(client, endpoint, token) default: - roleCreds, err = getCredentials(m.Client, endpoint) + roleCreds, err = getCredentials(client, endpoint) } if err != nil { @@ -224,6 +233,13 @@ func (m *IAM) Retrieve() (Value, error) { }, nil } +// Retrieve retrieves credentials from the EC2 service. +// Error will be returned if the request fails, or unable to extract +// the desired +func (m *IAM) Retrieve() (Value, error) { + return m.RetrieveWithCredContext(nil) +} + // A ec2RoleCredRespBody provides the shape for unmarshaling credential // request responses. type ec2RoleCredRespBody struct { diff --git a/vendor/github.com/minio/minio-go/v7/pkg/credentials/static.go b/vendor/github.com/minio/minio-go/v7/pkg/credentials/static.go index 7dde00b0a1..d90c98c84d 100644 --- a/vendor/github.com/minio/minio-go/v7/pkg/credentials/static.go +++ b/vendor/github.com/minio/minio-go/v7/pkg/credentials/static.go @@ -59,6 +59,11 @@ func (s *Static) Retrieve() (Value, error) { return s.Value, nil } +// RetrieveWithCredContext returns the static credentials. +func (s *Static) RetrieveWithCredContext(_ *CredContext) (Value, error) { + return s.Retrieve() +} + // IsExpired returns if the credentials are expired. // // For Static, the credentials never expired. diff --git a/vendor/github.com/minio/minio-go/v7/pkg/credentials/sts_client_grants.go b/vendor/github.com/minio/minio-go/v7/pkg/credentials/sts_client_grants.go index 62bfbb6b02..ef6f436b84 100644 --- a/vendor/github.com/minio/minio-go/v7/pkg/credentials/sts_client_grants.go +++ b/vendor/github.com/minio/minio-go/v7/pkg/credentials/sts_client_grants.go @@ -72,7 +72,8 @@ type ClientGrantsToken struct { type STSClientGrants struct { Expiry - // Required http Client to use when connecting to MinIO STS service. + // Optional http Client to use when connecting to MinIO STS service. + // (overrides default client in CredContext) Client *http.Client // MinIO endpoint to fetch STS credentials. @@ -90,16 +91,10 @@ type STSClientGrants struct { // NewSTSClientGrants returns a pointer to a new // Credentials object wrapping the STSClientGrants. func NewSTSClientGrants(stsEndpoint string, getClientGrantsTokenExpiry func() (*ClientGrantsToken, error)) (*Credentials, error) { - if stsEndpoint == "" { - return nil, errors.New("STS endpoint cannot be empty") - } if getClientGrantsTokenExpiry == nil { return nil, errors.New("Client grants access token and expiry retrieval function should be defined") } return New(&STSClientGrants{ - Client: &http.Client{ - Transport: http.DefaultTransport, - }, STSEndpoint: stsEndpoint, GetClientGrantsTokenExpiry: getClientGrantsTokenExpiry, }), nil @@ -162,10 +157,29 @@ func getClientGrantsCredentials(clnt *http.Client, endpoint string, return a, nil } -// Retrieve retrieves credentials from the MinIO service. -// Error will be returned if the request fails. -func (m *STSClientGrants) Retrieve() (Value, error) { - a, err := getClientGrantsCredentials(m.Client, m.STSEndpoint, m.GetClientGrantsTokenExpiry) +// RetrieveWithCredContext is like Retrieve() with cred context +func (m *STSClientGrants) RetrieveWithCredContext(cc *CredContext) (Value, error) { + if cc == nil { + cc = defaultCredContext + } + + client := m.Client + if client == nil { + client = cc.Client + } + if client == nil { + client = defaultCredContext.Client + } + + stsEndpoint := m.STSEndpoint + if stsEndpoint == "" { + stsEndpoint = cc.Endpoint + } + if stsEndpoint == "" { + return Value{}, errors.New("STS endpoint unknown") + } + + a, err := getClientGrantsCredentials(client, stsEndpoint, m.GetClientGrantsTokenExpiry) if err != nil { return Value{}, err } @@ -181,3 +195,9 @@ func (m *STSClientGrants) Retrieve() (Value, error) { SignerType: SignatureV4, }, nil } + +// Retrieve retrieves credentials from the MinIO service. +// Error will be returned if the request fails. +func (m *STSClientGrants) Retrieve() (Value, error) { + return m.RetrieveWithCredContext(nil) +} diff --git a/vendor/github.com/minio/minio-go/v7/pkg/credentials/sts_custom_identity.go b/vendor/github.com/minio/minio-go/v7/pkg/credentials/sts_custom_identity.go index 75e1a77d32..0021f9315b 100644 --- a/vendor/github.com/minio/minio-go/v7/pkg/credentials/sts_custom_identity.go +++ b/vendor/github.com/minio/minio-go/v7/pkg/credentials/sts_custom_identity.go @@ -53,6 +53,8 @@ type AssumeRoleWithCustomTokenResponse struct { type CustomTokenIdentity struct { Expiry + // Optional http Client to use when connecting to MinIO STS service. + // (overrides default client in CredContext) Client *http.Client // MinIO server STS endpoint to fetch STS credentials. @@ -69,9 +71,21 @@ type CustomTokenIdentity struct { RequestedExpiry time.Duration } -// Retrieve - to satisfy Provider interface; fetches credentials from MinIO. -func (c *CustomTokenIdentity) Retrieve() (value Value, err error) { - u, err := url.Parse(c.STSEndpoint) +// RetrieveWithCredContext with Retrieve optionally cred context +func (c *CustomTokenIdentity) RetrieveWithCredContext(cc *CredContext) (value Value, err error) { + if cc == nil { + cc = defaultCredContext + } + + stsEndpoint := c.STSEndpoint + if stsEndpoint == "" { + stsEndpoint = cc.Endpoint + } + if stsEndpoint == "" { + return Value{}, errors.New("STS endpoint unknown") + } + + u, err := url.Parse(stsEndpoint) if err != nil { return value, err } @@ -92,7 +106,15 @@ func (c *CustomTokenIdentity) Retrieve() (value Value, err error) { return value, err } - resp, err := c.Client.Do(req) + client := c.Client + if client == nil { + client = cc.Client + } + if client == nil { + client = defaultCredContext.Client + } + + resp, err := client.Do(req) if err != nil { return value, err } @@ -118,11 +140,15 @@ func (c *CustomTokenIdentity) Retrieve() (value Value, err error) { }, nil } +// Retrieve - to satisfy Provider interface; fetches credentials from MinIO. +func (c *CustomTokenIdentity) Retrieve() (value Value, err error) { + return c.RetrieveWithCredContext(nil) +} + // NewCustomTokenCredentials - returns credentials using the // AssumeRoleWithCustomToken STS API. func NewCustomTokenCredentials(stsEndpoint, token, roleArn string, optFuncs ...CustomTokenOpt) (*Credentials, error) { c := CustomTokenIdentity{ - Client: &http.Client{Transport: http.DefaultTransport}, STSEndpoint: stsEndpoint, Token: token, RoleArn: roleArn, diff --git a/vendor/github.com/minio/minio-go/v7/pkg/credentials/sts_ldap_identity.go b/vendor/github.com/minio/minio-go/v7/pkg/credentials/sts_ldap_identity.go index b8df289f20..e63997e6ef 100644 --- a/vendor/github.com/minio/minio-go/v7/pkg/credentials/sts_ldap_identity.go +++ b/vendor/github.com/minio/minio-go/v7/pkg/credentials/sts_ldap_identity.go @@ -20,6 +20,7 @@ package credentials import ( "bytes" "encoding/xml" + "errors" "fmt" "io" "net/http" @@ -55,7 +56,8 @@ type LDAPIdentityResult struct { type LDAPIdentity struct { Expiry - // Required http Client to use when connecting to MinIO STS service. + // Optional http Client to use when connecting to MinIO STS service. + // (overrides default client in CredContext) Client *http.Client // Exported STS endpoint to fetch STS credentials. @@ -77,7 +79,6 @@ type LDAPIdentity struct { // Identity. func NewLDAPIdentity(stsEndpoint, ldapUsername, ldapPassword string, optFuncs ...LDAPIdentityOpt) (*Credentials, error) { l := LDAPIdentity{ - Client: &http.Client{Transport: http.DefaultTransport}, STSEndpoint: stsEndpoint, LDAPUsername: ldapUsername, LDAPPassword: ldapPassword, @@ -113,7 +114,6 @@ func LDAPIdentityExpiryOpt(d time.Duration) LDAPIdentityOpt { // Deprecated: Use the `LDAPIdentityPolicyOpt` with `NewLDAPIdentity` instead. func NewLDAPIdentityWithSessionPolicy(stsEndpoint, ldapUsername, ldapPassword, policy string) (*Credentials, error) { return New(&LDAPIdentity{ - Client: &http.Client{Transport: http.DefaultTransport}, STSEndpoint: stsEndpoint, LDAPUsername: ldapUsername, LDAPPassword: ldapPassword, @@ -121,10 +121,22 @@ func NewLDAPIdentityWithSessionPolicy(stsEndpoint, ldapUsername, ldapPassword, p }), nil } -// Retrieve gets the credential by calling the MinIO STS API for +// RetrieveWithCredContext gets the credential by calling the MinIO STS API for // LDAP on the configured stsEndpoint. -func (k *LDAPIdentity) Retrieve() (value Value, err error) { - u, err := url.Parse(k.STSEndpoint) +func (k *LDAPIdentity) RetrieveWithCredContext(cc *CredContext) (value Value, err error) { + if cc == nil { + cc = defaultCredContext + } + + stsEndpoint := k.STSEndpoint + if stsEndpoint == "" { + stsEndpoint = cc.Endpoint + } + if stsEndpoint == "" { + return Value{}, errors.New("STS endpoint unknown") + } + + u, err := url.Parse(stsEndpoint) if err != nil { return value, err } @@ -148,7 +160,15 @@ func (k *LDAPIdentity) Retrieve() (value Value, err error) { req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - resp, err := k.Client.Do(req) + client := k.Client + if client == nil { + client = cc.Client + } + if client == nil { + client = defaultCredContext.Client + } + + resp, err := client.Do(req) if err != nil { return value, err } @@ -188,3 +208,9 @@ func (k *LDAPIdentity) Retrieve() (value Value, err error) { SignerType: SignatureV4, }, nil } + +// Retrieve gets the credential by calling the MinIO STS API for +// LDAP on the configured stsEndpoint. +func (k *LDAPIdentity) Retrieve() (value Value, err error) { + return k.RetrieveWithCredContext(defaultCredContext) +} diff --git a/vendor/github.com/minio/minio-go/v7/pkg/credentials/sts_tls_identity.go b/vendor/github.com/minio/minio-go/v7/pkg/credentials/sts_tls_identity.go index 10083502d1..c904bbeac7 100644 --- a/vendor/github.com/minio/minio-go/v7/pkg/credentials/sts_tls_identity.go +++ b/vendor/github.com/minio/minio-go/v7/pkg/credentials/sts_tls_identity.go @@ -20,8 +20,8 @@ import ( "crypto/tls" "encoding/xml" "errors" + "fmt" "io" - "net" "net/http" "net/url" "strconv" @@ -36,7 +36,12 @@ type CertificateIdentityOption func(*STSCertificateIdentity) // CertificateIdentityWithTransport returns a CertificateIdentityOption that // customizes the STSCertificateIdentity with the given http.RoundTripper. func CertificateIdentityWithTransport(t http.RoundTripper) CertificateIdentityOption { - return CertificateIdentityOption(func(i *STSCertificateIdentity) { i.Client.Transport = t }) + return CertificateIdentityOption(func(i *STSCertificateIdentity) { + if i.Client == nil { + i.Client = &http.Client{} + } + i.Client.Transport = t + }) } // CertificateIdentityWithExpiry returns a CertificateIdentityOption that @@ -53,6 +58,10 @@ func CertificateIdentityWithExpiry(livetime time.Duration) CertificateIdentityOp type STSCertificateIdentity struct { Expiry + // Optional http Client to use when connecting to MinIO STS service. + // (overrides default client in CredContext) + Client *http.Client + // STSEndpoint is the base URL endpoint of the STS API. // For example, https://minio.local:9000 STSEndpoint string @@ -68,50 +77,18 @@ type STSCertificateIdentity struct { // The default livetime is one hour. S3CredentialLivetime time.Duration - // Client is the HTTP client used to authenticate and fetch - // S3 credentials. - // - // A custom TLS client configuration can be specified by - // using a custom http.Transport: - // Client: http.Client { - // Transport: &http.Transport{ - // TLSClientConfig: &tls.Config{}, - // }, - // } - Client http.Client + // Certificate is the client certificate that is used for + // STS authentication. + Certificate tls.Certificate } -var _ Provider = (*STSWebIdentity)(nil) // compiler check - // NewSTSCertificateIdentity returns a STSCertificateIdentity that authenticates // to the given STS endpoint with the given TLS certificate and retrieves and // rotates S3 credentials. func NewSTSCertificateIdentity(endpoint string, certificate tls.Certificate, options ...CertificateIdentityOption) (*Credentials, error) { - if endpoint == "" { - return nil, errors.New("STS endpoint cannot be empty") - } - if _, err := url.Parse(endpoint); err != nil { - return nil, err - } identity := &STSCertificateIdentity{ STSEndpoint: endpoint, - Client: http.Client{ - Transport: &http.Transport{ - Proxy: http.ProxyFromEnvironment, - DialContext: (&net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - }).DialContext, - ForceAttemptHTTP2: true, - MaxIdleConns: 100, - IdleConnTimeout: 90 * time.Second, - TLSHandshakeTimeout: 10 * time.Second, - ExpectContinueTimeout: 5 * time.Second, - TLSClientConfig: &tls.Config{ - Certificates: []tls.Certificate{certificate}, - }, - }, - }, + Certificate: certificate, } for _, option := range options { option(identity) @@ -119,10 +96,21 @@ func NewSTSCertificateIdentity(endpoint string, certificate tls.Certificate, opt return New(identity), nil } -// Retrieve fetches a new set of S3 credentials from the configured -// STS API endpoint. -func (i *STSCertificateIdentity) Retrieve() (Value, error) { - endpointURL, err := url.Parse(i.STSEndpoint) +// RetrieveWithCredContext is Retrieve with cred context +func (i *STSCertificateIdentity) RetrieveWithCredContext(cc *CredContext) (Value, error) { + if cc == nil { + cc = defaultCredContext + } + + stsEndpoint := i.STSEndpoint + if stsEndpoint == "" { + stsEndpoint = cc.Endpoint + } + if stsEndpoint == "" { + return Value{}, errors.New("STS endpoint unknown") + } + + endpointURL, err := url.Parse(stsEndpoint) if err != nil { return Value{}, err } @@ -145,7 +133,28 @@ func (i *STSCertificateIdentity) Retrieve() (Value, error) { } req.Form.Add("DurationSeconds", strconv.FormatUint(uint64(livetime.Seconds()), 10)) - resp, err := i.Client.Do(req) + client := i.Client + if client == nil { + client = cc.Client + } + if client == nil { + client = defaultCredContext.Client + } + + tr, ok := client.Transport.(*http.Transport) + if !ok { + return Value{}, fmt.Errorf("CredContext should contain an http.Transport value") + } + + // Clone the HTTP transport (patch the TLS client certificate) + trCopy := tr.Clone() + trCopy.TLSClientConfig.Certificates = []tls.Certificate{i.Certificate} + + // Clone the HTTP client (patch the HTTP transport) + clientCopy := *client + clientCopy.Transport = trCopy + + resp, err := clientCopy.Do(req) if err != nil { return Value{}, err } @@ -193,6 +202,11 @@ func (i *STSCertificateIdentity) Retrieve() (Value, error) { }, nil } +// Retrieve fetches a new set of S3 credentials from the configured STS API endpoint. +func (i *STSCertificateIdentity) Retrieve() (Value, error) { + return i.RetrieveWithCredContext(defaultCredContext) +} + // Expiration returns the expiration time of the current S3 credentials. func (i *STSCertificateIdentity) Expiration() time.Time { return i.expiration } diff --git a/vendor/github.com/minio/minio-go/v7/pkg/credentials/sts_web_identity.go b/vendor/github.com/minio/minio-go/v7/pkg/credentials/sts_web_identity.go index 8c06bac60d..2352588930 100644 --- a/vendor/github.com/minio/minio-go/v7/pkg/credentials/sts_web_identity.go +++ b/vendor/github.com/minio/minio-go/v7/pkg/credentials/sts_web_identity.go @@ -69,7 +69,8 @@ type WebIdentityToken struct { type STSWebIdentity struct { Expiry - // Required http Client to use when connecting to MinIO STS service. + // Optional http Client to use when connecting to MinIO STS service. + // (overrides default client in CredContext) Client *http.Client // Exported STS endpoint to fetch STS credentials. @@ -97,16 +98,10 @@ type STSWebIdentity struct { // NewSTSWebIdentity returns a pointer to a new // Credentials object wrapping the STSWebIdentity. func NewSTSWebIdentity(stsEndpoint string, getWebIDTokenExpiry func() (*WebIdentityToken, error), opts ...func(*STSWebIdentity)) (*Credentials, error) { - if stsEndpoint == "" { - return nil, errors.New("STS endpoint cannot be empty") - } if getWebIDTokenExpiry == nil { return nil, errors.New("Web ID token and expiry retrieval function should be defined") } i := &STSWebIdentity{ - Client: &http.Client{ - Transport: http.DefaultTransport, - }, STSEndpoint: stsEndpoint, GetWebIDTokenExpiry: getWebIDTokenExpiry, } @@ -219,10 +214,29 @@ func getWebIdentityCredentials(clnt *http.Client, endpoint, roleARN, roleSession return a, nil } -// Retrieve retrieves credentials from the MinIO service. -// Error will be returned if the request fails. -func (m *STSWebIdentity) Retrieve() (Value, error) { - a, err := getWebIdentityCredentials(m.Client, m.STSEndpoint, m.RoleARN, m.roleSessionName, m.Policy, m.GetWebIDTokenExpiry) +// RetrieveWithCredContext is like Retrieve with optional cred context. +func (m *STSWebIdentity) RetrieveWithCredContext(cc *CredContext) (Value, error) { + if cc == nil { + cc = defaultCredContext + } + + client := m.Client + if client == nil { + client = cc.Client + } + if client == nil { + client = defaultCredContext.Client + } + + stsEndpoint := m.STSEndpoint + if stsEndpoint == "" { + stsEndpoint = cc.Endpoint + } + if stsEndpoint == "" { + return Value{}, errors.New("STS endpoint unknown") + } + + a, err := getWebIdentityCredentials(client, stsEndpoint, m.RoleARN, m.roleSessionName, m.Policy, m.GetWebIDTokenExpiry) if err != nil { return Value{}, err } @@ -239,6 +253,12 @@ func (m *STSWebIdentity) Retrieve() (Value, error) { }, nil } +// Retrieve retrieves credentials from the MinIO service. +// Error will be returned if the request fails. +func (m *STSWebIdentity) Retrieve() (Value, error) { + return m.RetrieveWithCredContext(nil) +} + // Expiration returns the expiration time of the credentials func (m *STSWebIdentity) Expiration() time.Time { return m.expiration diff --git a/vendor/github.com/minio/minio-go/v7/pkg/s3utils/utils.go b/vendor/github.com/minio/minio-go/v7/pkg/s3utils/utils.go index 0e63ce2f7d..80fd029d83 100644 --- a/vendor/github.com/minio/minio-go/v7/pkg/s3utils/utils.go +++ b/vendor/github.com/minio/minio-go/v7/pkg/s3utils/utils.go @@ -118,53 +118,53 @@ func GetRegionFromURL(endpointURL url.URL) string { if endpointURL == sentinelURL { return "" } - if endpointURL.Host == "s3-external-1.amazonaws.com" { + if endpointURL.Hostname() == "s3-external-1.amazonaws.com" { return "" } // if elb's are used we cannot calculate which region it may be, just return empty. - if elbAmazonRegex.MatchString(endpointURL.Host) || elbAmazonCnRegex.MatchString(endpointURL.Host) { + if elbAmazonRegex.MatchString(endpointURL.Hostname()) || elbAmazonCnRegex.MatchString(endpointURL.Hostname()) { return "" } // We check for FIPS dualstack matching first to avoid the non-greedy // regex for FIPS non-dualstack matching a dualstack URL - parts := amazonS3HostFIPSDualStack.FindStringSubmatch(endpointURL.Host) + parts := amazonS3HostFIPSDualStack.FindStringSubmatch(endpointURL.Hostname()) if len(parts) > 1 { return parts[1] } - parts = amazonS3HostFIPS.FindStringSubmatch(endpointURL.Host) + parts = amazonS3HostFIPS.FindStringSubmatch(endpointURL.Hostname()) if len(parts) > 1 { return parts[1] } - parts = amazonS3HostDualStack.FindStringSubmatch(endpointURL.Host) + parts = amazonS3HostDualStack.FindStringSubmatch(endpointURL.Hostname()) if len(parts) > 1 { return parts[1] } - parts = amazonS3HostHyphen.FindStringSubmatch(endpointURL.Host) + parts = amazonS3HostHyphen.FindStringSubmatch(endpointURL.Hostname()) if len(parts) > 1 { return parts[1] } - parts = amazonS3ChinaHost.FindStringSubmatch(endpointURL.Host) + parts = amazonS3ChinaHost.FindStringSubmatch(endpointURL.Hostname()) if len(parts) > 1 { return parts[1] } - parts = amazonS3ChinaHostDualStack.FindStringSubmatch(endpointURL.Host) + parts = amazonS3ChinaHostDualStack.FindStringSubmatch(endpointURL.Hostname()) if len(parts) > 1 { return parts[1] } - parts = amazonS3HostDot.FindStringSubmatch(endpointURL.Host) + parts = amazonS3HostDot.FindStringSubmatch(endpointURL.Hostname()) if len(parts) > 1 { return parts[1] } - parts = amazonS3HostPrivateLink.FindStringSubmatch(endpointURL.Host) + parts = amazonS3HostPrivateLink.FindStringSubmatch(endpointURL.Hostname()) if len(parts) > 1 { return parts[1] } diff --git a/vendor/github.com/minio/minio-go/v7/retry.go b/vendor/github.com/minio/minio-go/v7/retry.go index 4cc45920c4..ed954017ca 100644 --- a/vendor/github.com/minio/minio-go/v7/retry.go +++ b/vendor/github.com/minio/minio-go/v7/retry.go @@ -112,6 +112,7 @@ func isS3CodeRetryable(s3Code string) (ok bool) { // List of HTTP status codes which are retryable. var retryableHTTPStatusCodes = map[int]struct{}{ + http.StatusRequestTimeout: {}, 429: {}, // http.StatusTooManyRequests is not part of the Go 1.5 library, yet 499: {}, // client closed request, retry. A non-standard status code introduced by nginx. http.StatusInternalServerError: {}, diff --git a/vendor/github.com/prometheus/alertmanager/NOTICE b/vendor/github.com/prometheus/alertmanager/NOTICE index f5d0bbb421..e0dd624377 100644 --- a/vendor/github.com/prometheus/alertmanager/NOTICE +++ b/vendor/github.com/prometheus/alertmanager/NOTICE @@ -11,8 +11,3 @@ Bootstrap http://getbootstrap.com Copyright 2011-2014 Twitter, Inc. Licensed under the MIT License - -bootstrap-datetimepicker.js -http://www.eyecon.ro/bootstrap-datepicker -Copyright 2012 Stefan Petre -Licensed under the Apache License, Version 2.0 diff --git a/vendor/github.com/prometheus/alertmanager/api/api.go b/vendor/github.com/prometheus/alertmanager/api/api.go index 2e1e1ea425..6839d2d282 100644 --- a/vendor/github.com/prometheus/alertmanager/api/api.go +++ b/vendor/github.com/prometheus/alertmanager/api/api.go @@ -16,13 +16,14 @@ package api import ( "errors" "fmt" + "log/slog" "net/http" "runtime" "time" - "github.com/go-kit/log" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/model" + "github.com/prometheus/common/promslog" "github.com/prometheus/common/route" apiv2 "github.com/prometheus/alertmanager/api/v2" @@ -45,16 +46,20 @@ type API struct { inFlightSem chan struct{} } -// Options for the creation of an API object. Alerts, Silences, and StatusFunc -// are mandatory to set. The zero value for everything else is a safe default. +// Options for the creation of an API object. Alerts, Silences, AlertStatusFunc +// and GroupMutedFunc are mandatory. The zero value for everything else is a safe +// default. type Options struct { // Alerts to be used by the API. Mandatory. Alerts provider.Alerts // Silences to be used by the API. Mandatory. Silences *silence.Silences - // StatusFunc is used be the API to retrieve the AlertStatus of an + // AlertStatusFunc is used be the API to retrieve the AlertStatus of an // alert. Mandatory. - StatusFunc func(model.Fingerprint) types.AlertStatus + AlertStatusFunc func(model.Fingerprint) types.AlertStatus + // GroupMutedFunc is used be the API to know if an alert is muted. + // Mandatory. + GroupMutedFunc func(routeID, groupKey string) ([]string, bool) // Peer from the gossip cluster. If nil, no clustering will be used. Peer cluster.ClusterPeer // Timeout for all HTTP connections. The zero value (and negative @@ -66,7 +71,7 @@ type Options struct { // the concurrency limit. Concurrency int // Logger is used for logging, if nil, no logging will happen. - Logger log.Logger + Logger *slog.Logger // Registry is used to register Prometheus metrics. If nil, no metrics // registration will happen. Registry prometheus.Registerer @@ -83,8 +88,11 @@ func (o Options) validate() error { if o.Silences == nil { return errors.New("mandatory field Silences not set") } - if o.StatusFunc == nil { - return errors.New("mandatory field StatusFunc not set") + if o.AlertStatusFunc == nil { + return errors.New("mandatory field AlertStatusFunc not set") + } + if o.GroupMutedFunc == nil { + return errors.New("mandatory field GroupMutedFunc not set") } if o.GroupFunc == nil { return errors.New("mandatory field GroupFunc not set") @@ -100,7 +108,7 @@ func New(opts Options) (*API, error) { } l := opts.Logger if l == nil { - l = log.NewNopLogger() + l = promslog.NewNopLogger() } concurrency := opts.Concurrency if concurrency < 1 { @@ -113,10 +121,11 @@ func New(opts Options) (*API, error) { v2, err := apiv2.NewAPI( opts.Alerts, opts.GroupFunc, - opts.StatusFunc, + opts.AlertStatusFunc, + opts.GroupMutedFunc, opts.Silences, opts.Peer, - log.With(l, "version", "v2"), + l.With("version", "v2"), opts.Registry, ) if err != nil { @@ -145,7 +154,7 @@ func New(opts Options) (*API, error) { } return &API{ - deprecationRouter: NewV1DeprecationRouter(log.With(l, "version", "v1")), + deprecationRouter: NewV1DeprecationRouter(l.With("version", "v1")), v2: v2, requestsInFlight: requestsInFlight, concurrencyLimitExceeded: concurrencyLimitExceeded, @@ -162,7 +171,7 @@ func New(opts Options) (*API, error) { // true for the concurrency limit, with the exception that it is only applied to // GET requests. func (api *API) Register(r *route.Router, routePrefix string) *http.ServeMux { - // TODO(gotjosh) API V1 was removed as of version 0.28, when we reach 1.0.0 we should removed these deprecation warnings. + // TODO(gotjosh) API V1 was removed as of version 0.27, when we reach 1.0.0 we should removed these deprecation warnings. api.deprecationRouter.Register(r.WithPrefix("/api/v1")) mux := http.NewServeMux() diff --git a/vendor/github.com/prometheus/alertmanager/api/metrics/metrics.go b/vendor/github.com/prometheus/alertmanager/api/metrics/metrics.go index ea45acc2ee..439010166d 100644 --- a/vendor/github.com/prometheus/alertmanager/api/metrics/metrics.go +++ b/vendor/github.com/prometheus/alertmanager/api/metrics/metrics.go @@ -23,7 +23,7 @@ type Alerts struct { } // NewAlerts returns an *Alerts struct for the given API version. -// Since v1 was deprecated in 0.28, v2 is now hardcoded. +// Since v1 was deprecated in 0.27, v2 is now hardcoded. func NewAlerts(r prometheus.Registerer) *Alerts { numReceivedAlerts := prometheus.NewCounterVec(prometheus.CounterOpts{ Name: "alertmanager_alerts_received_total", diff --git a/vendor/github.com/prometheus/alertmanager/api/v1_deprecation_router.go b/vendor/github.com/prometheus/alertmanager/api/v1_deprecation_router.go index 3ebbbd076f..582e06ab41 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v1_deprecation_router.go +++ b/vendor/github.com/prometheus/alertmanager/api/v1_deprecation_router.go @@ -8,26 +8,24 @@ // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific l package api import ( "encoding/json" + "log/slog" "net/http" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/prometheus/common/route" ) // V1DeprecationRouter is the router to signal v1 users that the API v1 is now removed. type V1DeprecationRouter struct { - logger log.Logger + logger *slog.Logger } // NewV1DeprecationRouter returns a new V1DeprecationRouter. -func NewV1DeprecationRouter(l log.Logger) *V1DeprecationRouter { +func NewV1DeprecationRouter(l *slog.Logger) *V1DeprecationRouter { return &V1DeprecationRouter{ logger: l, } @@ -48,20 +46,20 @@ func (dr *V1DeprecationRouter) Register(r *route.Router) { } func (dr *V1DeprecationRouter) deprecationHandler(w http.ResponseWriter, req *http.Request) { - level.Warn(dr.logger).Log("msg", "v1 API received a request on a removed endpoint", "path", req.URL.Path, "method", req.Method) + dr.logger.Warn("v1 API received a request on a removed endpoint", "path", req.URL.Path, "method", req.Method) resp := struct { Status string `json:"status"` Error string `json:"error"` }{ "deprecated", - "The Alertmanager v1 API was deprecated in version 0.16.0 and is removed as of version 0.28.0 - please use the equivalent route in the v2 API", + "The Alertmanager v1 API was deprecated in version 0.16.0 and is removed as of version 0.27.0 - please use the equivalent route in the v2 API", } w.Header().Set("Content-Type", "application/json") w.WriteHeader(410) if err := json.NewEncoder(w).Encode(resp); err != nil { - level.Error(dr.logger).Log("msg", "failed to write response", "err", err) + dr.logger.Error("failed to write response", "err", err) } } diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/api.go b/vendor/github.com/prometheus/alertmanager/api/v2/api.go index b4f57e75e2..0e29375d40 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/api.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/api.go @@ -16,14 +16,13 @@ package v2 import ( "errors" "fmt" + "log/slog" "net/http" "regexp" "sort" "sync" "time" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/go-openapi/analysis" "github.com/go-openapi/loads" "github.com/go-openapi/runtime/middleware" @@ -45,7 +44,7 @@ import ( "github.com/prometheus/alertmanager/cluster" "github.com/prometheus/alertmanager/config" "github.com/prometheus/alertmanager/dispatch" - "github.com/prometheus/alertmanager/matchers/compat" + "github.com/prometheus/alertmanager/matcher/compat" "github.com/prometheus/alertmanager/pkg/labels" "github.com/prometheus/alertmanager/provider" "github.com/prometheus/alertmanager/silence" @@ -53,13 +52,14 @@ import ( "github.com/prometheus/alertmanager/types" ) -// API represents an Alertmanager API v2 +// API represents an Alertmanager API v2. type API struct { peer cluster.ClusterPeer silences *silence.Silences alerts provider.Alerts alertGroups groupsFn getAlertStatus getAlertStatusFn + groupMutedFunc groupMutedFunc uptime time.Time // mtx protects alertmanagerConfig, setAlertStatus and route. @@ -70,7 +70,7 @@ type API struct { route *dispatch.Route setAlertStatus setAlertStatusFn - logger log.Logger + logger *slog.Logger m *metrics.Alerts Handler http.Handler @@ -78,24 +78,27 @@ type API struct { type ( groupsFn func(func(*dispatch.Route) bool, func(*types.Alert, time.Time) bool) (dispatch.AlertGroups, map[prometheus_model.Fingerprint][]string) + groupMutedFunc func(routeID, groupKey string) ([]string, bool) getAlertStatusFn func(prometheus_model.Fingerprint) types.AlertStatus setAlertStatusFn func(prometheus_model.LabelSet) ) -// NewAPI returns a new Alertmanager API v2 +// NewAPI returns a new Alertmanager API v2. func NewAPI( alerts provider.Alerts, gf groupsFn, - sf getAlertStatusFn, + asf getAlertStatusFn, + gmf groupMutedFunc, silences *silence.Silences, peer cluster.ClusterPeer, - l log.Logger, + l *slog.Logger, r prometheus.Registerer, ) (*API, error) { api := API{ alerts: alerts, - getAlertStatus: sf, + getAlertStatus: asf, alertGroups: gf, + groupMutedFunc: gmf, peer: peer, silences: silences, logger: l, @@ -150,8 +153,8 @@ func setResponseHeaders(h http.Handler) http.Handler { }) } -func (api *API) requestLogger(req *http.Request) log.Logger { - return log.With(api.logger, "path", req.URL.Path, "method", req.Method) +func (api *API) requestLogger(req *http.Request) *slog.Logger { + return api.logger.With("path", req.URL.Path, "method", req.Method) } // Update sets the API struct members that may change between reloads of alertmanager. @@ -245,14 +248,14 @@ func (api *API) getAlertsHandler(params alert_ops.GetAlertsParams) middleware.Re matchers, err := parseFilter(params.Filter) if err != nil { - level.Debug(logger).Log("msg", "Failed to parse matchers", "err", err) + logger.Debug("Failed to parse matchers", "err", err) return alertgroup_ops.NewGetAlertGroupsBadRequest().WithPayload(err.Error()) } if params.Receiver != nil { receiverFilter, err = regexp.Compile("^(?:" + *params.Receiver + ")$") if err != nil { - level.Debug(logger).Log("msg", "Failed to compile receiver regex", "err", err) + logger.Debug("Failed to compile receiver regex", "err", err) return alert_ops. NewGetAlertsBadRequest(). WithPayload( @@ -290,14 +293,14 @@ func (api *API) getAlertsHandler(params alert_ops.GetAlertsParams) middleware.Re continue } - alert := AlertToOpenAPIAlert(a, api.getAlertStatus(a.Fingerprint()), receivers) + alert := AlertToOpenAPIAlert(a, api.getAlertStatus(a.Fingerprint()), receivers, nil) res = append(res, alert) } api.mtx.RUnlock() if err != nil { - level.Error(logger).Log("msg", "Failed to get alerts", "err", err) + logger.Error("Failed to get alerts", "err", err) return alert_ops.NewGetAlertsInternalServerError().WithPayload(err.Error()) } sort.Slice(res, func(i, j int) bool { @@ -357,12 +360,12 @@ func (api *API) postAlertsHandler(params alert_ops.PostAlertsParams) middleware. validAlerts = append(validAlerts, a) } if err := api.alerts.Put(validAlerts...); err != nil { - level.Error(logger).Log("msg", "Failed to create alerts", "err", err) + logger.Error("Failed to create alerts", "err", err) return alert_ops.NewPostAlertsInternalServerError().WithPayload(err.Error()) } if validationErrs.Len() > 0 { - level.Error(logger).Log("msg", "Failed to validate alerts", "err", validationErrs.Error()) + logger.Error("Failed to validate alerts", "err", validationErrs.Error()) return alert_ops.NewPostAlertsBadRequest().WithPayload(validationErrs.Error()) } @@ -374,7 +377,7 @@ func (api *API) getAlertGroupsHandler(params alertgroup_ops.GetAlertGroupsParams matchers, err := parseFilter(params.Filter) if err != nil { - level.Debug(logger).Log("msg", "Failed to parse matchers", "err", err) + logger.Debug("Failed to parse matchers", "err", err) return alertgroup_ops.NewGetAlertGroupsBadRequest().WithPayload(err.Error()) } @@ -382,7 +385,7 @@ func (api *API) getAlertGroupsHandler(params alertgroup_ops.GetAlertGroupsParams if params.Receiver != nil { receiverFilter, err = regexp.Compile("^(?:" + *params.Receiver + ")$") if err != nil { - level.Error(logger).Log("msg", "Failed to compile receiver regex", "err", err) + logger.Error("Failed to compile receiver regex", "err", err) return alertgroup_ops. NewGetAlertGroupsBadRequest(). WithPayload( @@ -407,6 +410,11 @@ func (api *API) getAlertGroupsHandler(params alertgroup_ops.GetAlertGroupsParams res := make(open_api_models.AlertGroups, 0, len(alertGroups)) for _, alertGroup := range alertGroups { + mutedBy, isMuted := api.groupMutedFunc(alertGroup.RouteID, alertGroup.GroupKey) + if !*params.Muted && isMuted { + continue + } + ag := &open_api_models.AlertGroup{ Receiver: &open_api_models.Receiver{Name: &alertGroup.Receiver}, Labels: ModelLabelSetToAPILabelSet(alertGroup.Labels), @@ -417,7 +425,7 @@ func (api *API) getAlertGroupsHandler(params alertgroup_ops.GetAlertGroupsParams fp := alert.Fingerprint() receivers := allReceivers[fp] status := api.getAlertStatus(fp) - apiAlert := AlertToOpenAPIAlert(alert, status, receivers) + apiAlert := AlertToOpenAPIAlert(alert, status, receivers, mutedBy) ag.Alerts = append(ag.Alerts, apiAlert) } res = append(res, ag) @@ -509,13 +517,13 @@ func (api *API) getSilencesHandler(params silence_ops.GetSilencesParams) middlew matchers, err := parseFilter(params.Filter) if err != nil { - level.Debug(logger).Log("msg", "Failed to parse matchers", "err", err) + logger.Debug("Failed to parse matchers", "err", err) return silence_ops.NewGetSilencesBadRequest().WithPayload(err.Error()) } psils, _, err := api.silences.Query() if err != nil { - level.Error(logger).Log("msg", "Failed to get silences", "err", err) + logger.Error("Failed to get silences", "err", err) return silence_ops.NewGetSilencesInternalServerError().WithPayload(err.Error()) } @@ -526,7 +534,7 @@ func (api *API) getSilencesHandler(params silence_ops.GetSilencesParams) middlew } silence, err := GettableSilenceFromProto(ps) if err != nil { - level.Error(logger).Log("msg", "Failed to unmarshal silence from proto", "err", err) + logger.Error("Failed to unmarshal silence from proto", "err", err) return silence_ops.NewGetSilencesInternalServerError().WithPayload(err.Error()) } sils = append(sils, &silence) @@ -545,9 +553,9 @@ var silenceStateOrder = map[types.SilenceState]int{ // SortSilences sorts first according to the state "active, pending, expired" // then by end time or start time depending on the state. -// active silences should show the next to expire first +// Active silences should show the next to expire first // pending silences are ordered based on which one starts next -// expired are ordered based on which one expired most recently +// expired are ordered based on which one expired most recently. func SortSilences(sils open_api_models.GettableSilences) { sort.Slice(sils, func(i, j int) bool { state1 := types.SilenceState(*sils[i].Status.State) @@ -605,18 +613,18 @@ func (api *API) getSilenceHandler(params silence_ops.GetSilenceParams) middlewar sils, _, err := api.silences.Query(silence.QIDs(params.SilenceID.String())) if err != nil { - level.Error(logger).Log("msg", "Failed to get silence by id", "err", err, "id", params.SilenceID.String()) + logger.Error("Failed to get silence by id", "err", err, "id", params.SilenceID.String()) return silence_ops.NewGetSilenceInternalServerError().WithPayload(err.Error()) } if len(sils) == 0 { - level.Error(logger).Log("msg", "Failed to find silence", "err", err, "id", params.SilenceID.String()) + logger.Error("Failed to find silence", "err", err, "id", params.SilenceID.String()) return silence_ops.NewGetSilenceNotFound() } sil, err := GettableSilenceFromProto(sils[0]) if err != nil { - level.Error(logger).Log("msg", "Failed to convert unmarshal from proto", "err", err) + logger.Error("Failed to convert unmarshal from proto", "err", err) return silence_ops.NewGetSilenceInternalServerError().WithPayload(err.Error()) } @@ -628,7 +636,7 @@ func (api *API) deleteSilenceHandler(params silence_ops.DeleteSilenceParams) mid sid := params.SilenceID.String() if err := api.silences.Expire(sid); err != nil { - level.Error(logger).Log("msg", "Failed to expire silence", "err", err) + logger.Error("Failed to expire silence", "err", err) if errors.Is(err, silence.ErrNotFound) { return silence_ops.NewDeleteSilenceNotFound() } @@ -642,7 +650,7 @@ func (api *API) postSilencesHandler(params silence_ops.PostSilencesParams) middl sil, err := PostableSilenceToProto(params.Silence) if err != nil { - level.Error(logger).Log("msg", "Failed to marshal silence to proto", "err", err) + logger.Error("Failed to marshal silence to proto", "err", err) return silence_ops.NewPostSilencesBadRequest().WithPayload( fmt.Sprintf("failed to convert API silence to internal silence: %v", err.Error()), ) @@ -650,19 +658,18 @@ func (api *API) postSilencesHandler(params silence_ops.PostSilencesParams) middl if sil.StartsAt.After(sil.EndsAt) || sil.StartsAt.Equal(sil.EndsAt) { msg := "Failed to create silence: start time must be before end time" - level.Error(logger).Log("msg", msg, "starts_at", sil.StartsAt, "ends_at", sil.EndsAt) + logger.Error(msg, "starts_at", sil.StartsAt, "ends_at", sil.EndsAt) return silence_ops.NewPostSilencesBadRequest().WithPayload(msg) } if sil.EndsAt.Before(time.Now()) { msg := "Failed to create silence: end time can't be in the past" - level.Error(logger).Log("msg", msg, "ends_at", sil.EndsAt) + logger.Error(msg, "ends_at", sil.EndsAt) return silence_ops.NewPostSilencesBadRequest().WithPayload(msg) } - sid, err := api.silences.Set(sil) - if err != nil { - level.Error(logger).Log("msg", "Failed to create silence", "err", err) + if err = api.silences.Set(sil); err != nil { + logger.Error("Failed to create silence", "err", err) if errors.Is(err, silence.ErrNotFound) { return silence_ops.NewPostSilencesNotFound().WithPayload(err.Error()) } @@ -670,7 +677,7 @@ func (api *API) postSilencesHandler(params silence_ops.PostSilencesParams) middl } return silence_ops.NewPostSilencesOK().WithPayload(&silence_ops.PostSilencesOKBody{ - SilenceID: sid, + SilenceID: sil.Id, }) } diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/client/alertgroup/get_alert_groups_parameters.go b/vendor/github.com/prometheus/alertmanager/api/v2/client/alertgroup/get_alert_groups_parameters.go index 1196ade8f1..81020fcf67 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/client/alertgroup/get_alert_groups_parameters.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/client/alertgroup/get_alert_groups_parameters.go @@ -98,6 +98,14 @@ type GetAlertGroupsParams struct { */ Inhibited *bool + /* Muted. + + Show muted alerts + + Default: true + */ + Muted *bool + /* Receiver. A regex matching receivers to filter alerts by @@ -134,12 +142,15 @@ func (o *GetAlertGroupsParams) SetDefaults() { inhibitedDefault = bool(true) + mutedDefault = bool(true) + silencedDefault = bool(true) ) val := GetAlertGroupsParams{ Active: &activeDefault, Inhibited: &inhibitedDefault, + Muted: &mutedDefault, Silenced: &silencedDefault, } @@ -215,6 +226,17 @@ func (o *GetAlertGroupsParams) SetInhibited(inhibited *bool) { o.Inhibited = inhibited } +// WithMuted adds the muted to the get alert groups params +func (o *GetAlertGroupsParams) WithMuted(muted *bool) *GetAlertGroupsParams { + o.SetMuted(muted) + return o +} + +// SetMuted adds the muted to the get alert groups params +func (o *GetAlertGroupsParams) SetMuted(muted *bool) { + o.Muted = muted +} + // WithReceiver adds the receiver to the get alert groups params func (o *GetAlertGroupsParams) WithReceiver(receiver *string) *GetAlertGroupsParams { o.SetReceiver(receiver) @@ -290,6 +312,23 @@ func (o *GetAlertGroupsParams) WriteToRequest(r runtime.ClientRequest, reg strfm } } + if o.Muted != nil { + + // query param muted + var qrMuted bool + + if o.Muted != nil { + qrMuted = *o.Muted + } + qMuted := swag.FormatBool(qrMuted) + if qMuted != "" { + + if err := r.SetQueryParam("muted", qMuted); err != nil { + return err + } + } + } + if o.Receiver != nil { // query param receiver diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/compat.go b/vendor/github.com/prometheus/alertmanager/api/v2/compat.go index 112bfc4f2f..8954f2f752 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/compat.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/compat.go @@ -117,7 +117,7 @@ func PostableSilenceToProto(s *open_api_models.PostableSilence) (*silencepb.Sile } // AlertToOpenAPIAlert converts internal alerts, alert types, and receivers to *open_api_models.GettableAlert. -func AlertToOpenAPIAlert(alert *types.Alert, status types.AlertStatus, receivers []string) *open_api_models.GettableAlert { +func AlertToOpenAPIAlert(alert *types.Alert, status types.AlertStatus, receivers, mutedBy []string) *open_api_models.GettableAlert { startsAt := strfmt.DateTime(alert.StartsAt) updatedAt := strfmt.DateTime(alert.UpdatedAt) endsAt := strfmt.DateTime(alert.EndsAt) @@ -128,7 +128,13 @@ func AlertToOpenAPIAlert(alert *types.Alert, status types.AlertStatus, receivers } fp := alert.Fingerprint().String() + state := string(status.State) + if len(mutedBy) > 0 { + // If the alert is muted, change the state to suppressed. + state = open_api_models.AlertStatusStateSuppressed + } + aa := &open_api_models.GettableAlert{ Alert: open_api_models.Alert{ GeneratorURL: strfmt.URI(alert.GeneratorURL), @@ -144,6 +150,7 @@ func AlertToOpenAPIAlert(alert *types.Alert, status types.AlertStatus, receivers State: &state, SilencedBy: status.SilencedBy, InhibitedBy: status.InhibitedBy, + MutedBy: mutedBy, }, } @@ -155,6 +162,10 @@ func AlertToOpenAPIAlert(alert *types.Alert, status types.AlertStatus, receivers aa.Status.InhibitedBy = []string{} } + if aa.Status.MutedBy == nil { + aa.Status.MutedBy = []string{} + } + return aa } diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/models/alert_status.go b/vendor/github.com/prometheus/alertmanager/api/v2/models/alert_status.go index ae1f248c99..2fa4f2314b 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/models/alert_status.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/models/alert_status.go @@ -38,6 +38,10 @@ type AlertStatus struct { // Required: true InhibitedBy []string `json:"inhibitedBy"` + // muted by + // Required: true + MutedBy []string `json:"mutedBy"` + // silenced by // Required: true SilencedBy []string `json:"silencedBy"` @@ -56,6 +60,10 @@ func (m *AlertStatus) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := m.validateMutedBy(formats); err != nil { + res = append(res, err) + } + if err := m.validateSilencedBy(formats); err != nil { res = append(res, err) } @@ -79,6 +87,15 @@ func (m *AlertStatus) validateInhibitedBy(formats strfmt.Registry) error { return nil } +func (m *AlertStatus) validateMutedBy(formats strfmt.Registry) error { + + if err := validate.Required("mutedBy", "body", m.MutedBy); err != nil { + return err + } + + return nil +} + func (m *AlertStatus) validateSilencedBy(formats strfmt.Registry) error { if err := validate.Required("silencedBy", "body", m.SilencedBy); err != nil { diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/openapi.yaml b/vendor/github.com/prometheus/alertmanager/api/v2/openapi.yaml index 549cc33e7f..bc525ff37a 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/openapi.yaml +++ b/vendor/github.com/prometheus/alertmanager/api/v2/openapi.yaml @@ -223,6 +223,11 @@ paths: type: boolean description: Show inhibited alerts default: true + - in: query + name: muted + type: boolean + description: Show muted alerts + default: true - name: filter in: query description: A list of matchers to filter alerts by @@ -501,10 +506,15 @@ definitions: type: array items: type: string + mutedBy: + type: array + items: + type: string required: - state - silencedBy - inhibitedBy + - mutedBy receiver: type: object properties: diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/restapi/embedded_spec.go b/vendor/github.com/prometheus/alertmanager/api/v2/restapi/embedded_spec.go index 0e23efd060..37938bdc14 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/restapi/embedded_spec.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/restapi/embedded_spec.go @@ -177,6 +177,13 @@ func init() { "name": "inhibited", "in": "query" }, + { + "type": "boolean", + "default": true, + "description": "Show muted alerts", + "name": "muted", + "in": "query" + }, { "type": "array", "items": { @@ -433,7 +440,8 @@ func init() { "required": [ "state", "silencedBy", - "inhibitedBy" + "inhibitedBy", + "mutedBy" ], "properties": { "inhibitedBy": { @@ -442,6 +450,12 @@ func init() { "type": "string" } }, + "mutedBy": { + "type": "array", + "items": { + "type": "string" + } + }, "silencedBy": { "type": "array", "items": { @@ -979,6 +993,13 @@ func init() { "name": "inhibited", "in": "query" }, + { + "type": "boolean", + "default": true, + "description": "Show muted alerts", + "name": "muted", + "in": "query" + }, { "type": "array", "items": { @@ -1256,7 +1277,8 @@ func init() { "required": [ "state", "silencedBy", - "inhibitedBy" + "inhibitedBy", + "mutedBy" ], "properties": { "inhibitedBy": { @@ -1265,6 +1287,12 @@ func init() { "type": "string" } }, + "mutedBy": { + "type": "array", + "items": { + "type": "string" + } + }, "silencedBy": { "type": "array", "items": { diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/restapi/operations/alertgroup/get_alert_groups_parameters.go b/vendor/github.com/prometheus/alertmanager/api/v2/restapi/operations/alertgroup/get_alert_groups_parameters.go index 0f5712dc42..e8b3e72eb3 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/restapi/operations/alertgroup/get_alert_groups_parameters.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/restapi/operations/alertgroup/get_alert_groups_parameters.go @@ -39,6 +39,7 @@ func NewGetAlertGroupsParams() GetAlertGroupsParams { activeDefault = bool(true) inhibitedDefault = bool(true) + mutedDefault = bool(true) silencedDefault = bool(true) ) @@ -48,6 +49,8 @@ func NewGetAlertGroupsParams() GetAlertGroupsParams { Inhibited: &inhibitedDefault, + Muted: &mutedDefault, + Silenced: &silencedDefault, } } @@ -76,6 +79,11 @@ type GetAlertGroupsParams struct { Default: true */ Inhibited *bool + /*Show muted alerts + In: query + Default: true + */ + Muted *bool /*A regex matching receivers to filter alerts by In: query */ @@ -113,6 +121,11 @@ func (o *GetAlertGroupsParams) BindRequest(r *http.Request, route *middleware.Ma res = append(res, err) } + qMuted, qhkMuted, _ := qs.GetOK("muted") + if err := o.bindMuted(qMuted, qhkMuted, route.Formats); err != nil { + res = append(res, err) + } + qReceiver, qhkReceiver, _ := qs.GetOK("receiver") if err := o.bindReceiver(qReceiver, qhkReceiver, route.Formats); err != nil { res = append(res, err) @@ -198,6 +211,30 @@ func (o *GetAlertGroupsParams) bindInhibited(rawData []string, hasKey bool, form return nil } +// bindMuted binds and validates parameter Muted from query. +func (o *GetAlertGroupsParams) bindMuted(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetAlertGroupsParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("muted", "query", "bool", raw) + } + o.Muted = &value + + return nil +} + // bindReceiver binds and validates parameter Receiver from query. func (o *GetAlertGroupsParams) bindReceiver(rawData []string, hasKey bool, formats strfmt.Registry) error { var raw string diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/restapi/operations/alertgroup/get_alert_groups_urlbuilder.go b/vendor/github.com/prometheus/alertmanager/api/v2/restapi/operations/alertgroup/get_alert_groups_urlbuilder.go index b89f54779e..d229a4a5b2 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/restapi/operations/alertgroup/get_alert_groups_urlbuilder.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/restapi/operations/alertgroup/get_alert_groups_urlbuilder.go @@ -32,6 +32,7 @@ type GetAlertGroupsURL struct { Active *bool Filter []string Inhibited *bool + Muted *bool Receiver *string Silenced *bool @@ -99,6 +100,14 @@ func (o *GetAlertGroupsURL) Build() (*url.URL, error) { qs.Set("inhibited", inhibitedQ) } + var mutedQ string + if o.Muted != nil { + mutedQ = swag.FormatBool(*o.Muted) + } + if mutedQ != "" { + qs.Set("muted", mutedQ) + } + var receiverQ string if o.Receiver != nil { receiverQ = *o.Receiver diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/testing.go b/vendor/github.com/prometheus/alertmanager/api/v2/testing.go index c813d350d3..7665a19f67 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/testing.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/testing.go @@ -14,19 +14,17 @@ package v2 import ( - "encoding/json" "testing" "time" "github.com/go-openapi/strfmt" - "github.com/stretchr/testify/require" open_api_models "github.com/prometheus/alertmanager/api/v2/models" "github.com/prometheus/alertmanager/pkg/labels" "github.com/prometheus/alertmanager/silence/silencepb" ) -func createSilence(t *testing.T, ID, creator string, start, ends time.Time) (open_api_models.PostableSilence, []byte) { +func createSilence(t *testing.T, ID, creator string, start, ends time.Time) open_api_models.PostableSilence { t.Helper() comment := "test" @@ -46,10 +44,7 @@ func createSilence(t *testing.T, ID, creator string, start, ends time.Time) (ope Comment: &comment, }, } - b, err := json.Marshal(&sil) - require.NoError(t, err) - - return sil, b + return sil } func createSilenceMatcher(t *testing.T, name, pattern string, matcherType silencepb.Matcher_Type) *silencepb.Matcher { diff --git a/vendor/github.com/prometheus/alertmanager/asset/assets_vfsdata.go b/vendor/github.com/prometheus/alertmanager/asset/assets_vfsdata.go index f74112ad01..3dd06e052b 100644 --- a/vendor/github.com/prometheus/alertmanager/asset/assets_vfsdata.go +++ b/vendor/github.com/prometheus/alertmanager/asset/assets_vfsdata.go @@ -1,7 +1,6 @@ // Code generated by vfsgen; DO NOT EDIT. //go:build !dev -// +build !dev package asset @@ -10,7 +9,6 @@ import ( "compress/gzip" "fmt" "io" - "io/ioutil" "net/http" "os" pathpkg "path" @@ -152,9 +150,9 @@ var Assets = func() http.FileSystem { "/static/script.js": &vfsgen۰CompressedFileInfo{ name: "script.js", modTime: time.Date(1970, 1, 1, 0, 0, 1, 0, time.UTC), - uncompressedSize: 110210, + uncompressedSize: 110586, - compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\xdc\xbd\x09\x7b\xdb\xba\x92\x28\xf8\x57\x64\xb6\x5b\x17\x38\x2a\x31\x94\xb7\x24\x94\x71\x35\xce\xe2\x2c\x27\xb1\x13\xc7\x59\x7d\xfc\xf2\x40\x0a\x92\x69\x4b\xa0\x02\x82\x92\x1d\x4b\xfd\x37\xe6\x07\xcd\x1f\x9b\x0f\x00\x17\x90\x5a\x92\xd3\x7d\xfb\xbd\x37\x73\xef\xf9\x1c\x8a\x2c\x14\x0a\x5b\xa1\x36\x14\xb6\x06\x29\x0f\x65\x14\x73\xc4\xf1\xbd\x93\x26\xac\x91\x48\x11\x85\xd2\xe9\xe6\x1f\x1a\x02\x71\x10\x20\xf1\xbd\x60\x32\x15\xbc\x21\x5d\x4a\x38\x48\x77\x40\x04\xc8\x45\x01\x36\x42\x25\x88\x40\x3b\x20\xa1\x40\x2d\x8a\x0f\x76\x6d\x39\x3a\x24\x80\xe3\xc5\x02\x97\xa8\xfa\x88\x59\xa8\x76\x81\x95\xa8\xe4\x32\xaa\x8d\xd8\x19\x92\x60\xf0\xdb\x15\x48\x94\x5a\x15\xec\x41\x5a\x56\xc0\x96\xb1\xfd\xdd\x3a\x53\xc4\xa0\xa8\xd5\xae\x36\x44\xd4\xaa\x76\x1f\x68\x59\x6d\xba\x8c\xf0\x5f\x40\x09\x45\x29\xd8\xb4\xd8\xc4\x30\x14\x5a\xc4\x1c\x40\x58\x12\x43\x97\x71\xfe\xf7\xd0\x17\x22\x0a\x35\x0a\x6d\x12\x53\x14\x5b\x24\x3e\x84\xb8\x24\x31\x5c\x46\xfb\xbf\x8c\xea\x18\x85\xb0\x4c\xb7\x4d\x38\x45\x91\x45\xf8\x23\x88\x4a\xc2\xe3\x65\xcc\xff\x3b\xdb\x12\xa1\x18\x56\xb6\xc6\x6e\x4e\x8c\x06\x56\x73\x1e\xc3\xa0\x6c\x4e\xb4\x8c\xfc\xff\xb0\x16\x0e\x50\x04\xeb\xda\x68\x37\x72\x56\x63\x73\x3b\x84\x10\xee\xd2\x1e\x77\x07\x48\xbd\xf7\x55\x3d\x48\x5a\x25\xee\x4c\x09\x28\x89\xdc\xad\x96\x01\x56\x94\x42\xcc\x2a\x78\x9b\x17\x84\xb2\xc9\x7b\xf5\xa2\x90\xda\x85\x51\x6a\x95\x9f\x96\xe5\xa1\xec\xc7\xfd\x65\x0c\x40\x6b\x38\x10\xb5\xd0\x0c\x6c\x34\x50\x8e\xd1\xc1\x2a\x44\x10\x2e\xa3\x42\xa1\x85\x2d\xa8\x62\x83\x72\x1a\x3c\x5c\x8d\x0f\xe2\x95\x18\x51\x8c\x17\x53\x2a\x1a\x11\xe9\xa3\x72\x38\xcd\xd0\x0c\x62\x81\xd4\x37\x46\x8e\x84\xa0\x77\x88\x63\x48\x89\xd7\x4d\x0f\x79\x37\x6d\xb5\x30\xbb\x48\x2f\x89\x44\xa2\x95\xe2\x6e\xce\xff\x17\x18\x12\x32\xaa\x60\x2a\xf1\xc8\x12\x0f\x23\x5e\x97\x1d\xf2\x66\x53\xb8\x41\x97\xb5\x5a\x58\x5e\xb0\x4b\x22\x5c\x0a\x82\xa8\x57\xc5\xe6\x37\x62\x7c\x28\xaf\x08\x83\x53\xb5\xb5\xe0\x05\x86\x6d\x82\xea\x15\xe4\x8b\xe5\x82\x5f\x2e\x30\x6c\x6a\x48\x8e\x10\xd2\x8c\x16\x86\x81\x12\xaf\x4b\x0f\x59\x97\xb6\x5a\x38\xbd\xa0\x97\x44\x5e\xd0\xcb\x9c\x82\xf4\x82\x5f\x12\x01\xe9\x02\xc3\xfa\x66\x89\x1c\x6b\xde\x53\xb2\xd5\xc9\xfb\x4a\x96\x7d\x25\x2e\xd2\x02\x2f\xbb\x90\x97\x84\x03\xfb\x7d\x7a\x15\x32\xa6\x91\x09\xa2\x56\x8f\xbc\x48\x2f\x41\x14\x5d\x2f\x7e\x13\x53\xbb\xd3\xf5\x0e\x09\xeb\xb2\x76\xbb\x40\xc4\x6a\x88\x70\xf7\xef\xb4\x75\x45\x4b\x39\x52\x6d\xad\x4c\x8b\xff\xf2\xa8\x68\x8e\xd1\xa2\xa0\x46\xa7\xc0\x9c\xae\xc4\x5c\xcc\x9e\x64\x14\x85\x4c\xb7\xe0\x17\x14\x88\x92\x02\xde\x66\x40\x73\x3a\x5a\x28\x2d\xa8\x3b\x4c\x7b\xf9\xa3\x9f\x62\x0c\x21\xf1\xba\xe1\x21\xeb\x86\xad\x16\xa6\x17\xa1\x1a\xdf\xf0\xb2\xab\x70\x9a\x2f\x69\xfe\xa5\xc5\xd4\x9c\x0a\x8b\xb1\xa7\x2b\x26\x93\x35\x8a\x6b\x3e\x85\x31\x4f\xe2\x11\x73\x47\xf1\x10\xf1\x96\xe3\x37\x9c\xd6\x18\x61\x0c\x62\x81\x4b\xe9\x71\x8c\x72\x78\xe7\x30\xe2\x92\x09\x4e\x47\xc9\x3f\x9d\x92\x6f\x5c\x29\x5e\x2d\xaf\x44\x3c\x6b\x3c\x17\x22\x16\xc8\xb9\x92\x72\x92\xf8\x0f\x1e\x0c\x23\x79\x95\x06\x6e\x18\x8f\x1f\xb0\xd1\xf8\x41\x18\x0b\xf6\x20\x18\xc5\xc1\x83\x8e\xeb\xb9\xde\x83\xab\x88\xcb\xe4\x81\xd3\xe2\x2d\xc7\x1d\xf7\x1d\x8b\x15\x0d\x6b\x53\x04\x18\xb9\xb8\x84\x94\x4c\x74\x37\x7b\xc0\x70\x37\x6d\x36\x91\x24\xcc\x9d\xc4\x13\x84\x71\x57\x7d\x93\x2e\x05\xe9\x06\xfa\xbb\x35\x9c\x05\xd6\x49\xc9\xee\xa3\x01\xea\x78\xde\xa1\xc4\xf9\x74\x72\x27\x69\x72\x85\x4e\x75\xbd\x18\xb6\xbc\x6e\x34\x40\x9c\x10\x22\x32\x08\xf3\xc6\x89\x83\x6b\x16\x4a\x67\x8b\xc8\xbb\x09\x8b\x07\x0d\x3e\x9f\xf3\x74\x34\x52\xfc\xb1\x78\xca\x8b\x38\x79\xc5\x0e\x29\xc0\x9b\xcd\x2b\xb4\x8f\x61\xab\xd3\xcd\xdb\x96\x36\x22\xde\xe0\xee\xf6\xa1\xd7\x6c\x22\x4e\x06\x52\xf1\x32\xa1\xfe\x55\x84\x70\x1c\x0d\xd0\xd6\x04\x71\xbd\x32\xd5\x1f\xd9\xea\xa8\xe6\x65\x54\x75\xba\x39\x79\x9a\xe5\xde\x90\x11\x1a\x62\x38\x22\xab\x07\x7c\x6b\x98\x4d\xdc\x72\x74\x3f\xe4\x13\x77\x65\xeb\xf2\xee\xd1\x3d\xd1\xf3\x7c\x7e\x28\x7a\xed\x8e\xdf\x51\x7d\xb1\xc5\xdd\xed\xec\x3b\x92\xe4\x03\xe2\x8a\xd3\xba\x14\xe3\xf9\x3c\xfb\x1d\x80\x70\x03\x8c\x7b\xd2\x57\xbf\x42\x10\x6e\x88\x75\xbb\xbb\xdc\x0d\x34\x9f\x6e\x36\xb7\xaa\x65\xbb\x9c\xe8\x72\x8a\x63\x17\x43\x28\xe7\x73\x85\xad\xd7\xf1\x85\x1b\xa8\xfa\x3d\xb3\xc1\x3c\x5f\xd3\x4c\xd3\x28\x7c\xe8\x2d\x30\x5c\xaf\x65\xed\x19\x50\x67\xfd\xf2\xf0\x0e\x3f\xe4\x0b\x7d\x2d\x04\xc9\x41\x30\x3c\x5d\x26\x27\xfb\x5a\xf0\xc1\x43\xaf\xd7\x97\xbe\xe8\x8d\xa4\x9f\xc8\x05\x86\x57\xc4\x2b\x87\xe2\xd4\x46\x7d\x4f\x7d\x0e\x81\x2f\x16\xe5\xf4\xfd\x5e\xe5\x45\x39\x04\x84\xbe\xb4\xa0\xce\x0d\x96\x7c\xd9\xdc\x2f\x74\x8f\x4b\x3d\xcb\xb0\xd9\x22\x2e\xe4\x65\xf9\x52\x98\x97\x42\xbd\x2c\x78\xab\x2a\xfd\x85\x8c\xd0\x99\x35\x53\xce\x0c\x62\x35\x4f\x94\x86\xc9\x87\xd6\xb4\x2e\xe6\x49\x4b\x64\x53\x23\xc8\x5f\x89\xae\x61\xf2\x27\x66\x90\xb3\x11\xee\x5a\x9c\x5a\xcd\x06\xf3\x16\x33\xc2\xdc\xa0\x04\xcd\xc7\x5f\xd3\x73\x4c\xee\xb7\x7d\x6f\x51\x12\x74\x52\xe9\xaf\x6d\xbf\x03\x45\x9f\x29\xf8\x37\x64\x84\x4e\x2c\xfa\x3f\x2b\x36\x95\x57\x2b\xc8\x31\x48\xc2\x33\xde\xdb\x95\xed\x76\x17\x0b\x55\xf1\x85\xac\x6e\x5c\x45\xf1\x67\xd5\xe2\x17\x97\x16\xd9\xc2\x70\x0f\xee\x52\xab\xa4\x82\x7b\xbd\x51\x04\xba\xb8\xec\xea\x35\x20\x95\x74\xa2\x66\x3c\x48\x22\x55\x2f\x18\x74\x7a\x77\xd2\x2c\x8d\x96\xec\xec\xb3\x92\x43\x31\x7c\x24\x48\xd6\x30\x2b\xb6\x56\x30\x15\x1b\x77\xb3\xc9\xaa\x15\x80\xee\x66\x9c\x9a\x6a\xee\xca\x6a\x80\x55\xab\x4a\x55\x55\xe1\x52\x3d\x4a\xe8\xcd\x6b\xa2\x4b\x35\x35\x9b\xe9\xaa\xea\x20\x25\xa9\x1b\x60\x6a\x2a\xbd\xad\x56\x0a\x69\xb5\x62\xaa\x2a\x66\x2b\x2a\x56\xd2\x72\x5e\x75\xb8\xba\xea\x66\x93\xae\xaf\x1f\x28\xa1\x6e\x80\x43\x43\xc5\x74\x99\x0a\xa0\x55\x4a\xc2\xda\xea\x97\x50\x2a\x26\x9f\x91\x9a\x14\x6e\x12\x0b\xb9\x8e\xc5\x68\x6e\xae\x59\xf9\x42\xff\x07\x3f\x2b\xfc\xe8\x37\xb1\x91\x99\x82\xb4\xe7\x25\x21\x24\x91\x3d\xcf\x57\x0f\x7d\xa9\x79\xb2\xae\x60\x1d\xa3\xe2\x2d\x25\x83\xc1\xcb\xb5\xdc\x90\xb7\x37\xc8\x09\xfc\x0f\x5d\xfa\xed\xfa\xd2\x0f\x36\x95\x7e\x20\xe6\x9e\xfe\xfc\x96\xca\x2b\x77\x12\xcf\xd6\xcb\x2a\xff\xce\x57\xe1\xf9\x77\xc2\xf3\x96\x7b\x6a\xab\xed\x5d\xa1\x4e\x07\xfb\xde\xa1\x68\x36\xf9\xa1\x37\x9f\x0b\xb5\x7b\x7a\x87\xbc\x27\x5a\xdc\xcf\xa4\x4d\x5d\x19\x95\x94\xef\x60\xcd\x82\x3e\x11\xfd\x26\x64\xd1\x08\xbe\x99\xe7\xc1\x28\x8e\x05\xfc\x30\x3f\x44\x9c\xf2\x3e\x3c\x31\x3f\x46\xf1\xb0\xbb\xae\x39\xcd\xe6\xa6\xc6\xce\xe7\x9b\xbe\x6e\x11\xa2\x84\x2b\x45\xcf\x7b\xb2\x69\xac\xba\x7f\xeb\xe3\xef\xc9\xd2\x66\x57\xa0\x44\xb8\xe1\x15\x15\x4f\xe3\x3e\x3b\x92\x28\xc5\x5d\x7a\xb8\xbf\xbf\xf3\xf8\x60\x3e\xdf\x3f\xd8\xed\x3c\x3e\xa4\x3d\x64\x4b\xdc\xa0\x44\x70\xdf\x7e\xd5\x12\x17\x69\xab\xa3\xbf\x90\x1d\xbc\x28\x44\xa8\xeb\x38\xe2\xc8\x71\xf0\x46\xc5\xe6\xe2\x12\x2a\xb2\xb1\xd1\x41\x0a\xd2\x94\x88\x13\x2e\x51\x98\xb6\x5a\x10\x56\xa9\x0c\xe7\x73\x44\x5b\xa6\x80\xa2\x10\x38\xa2\x58\xb1\x02\xbd\xb2\x69\x41\x96\xb4\xc8\xea\xfe\x2d\xbd\x28\xa7\x49\x1a\x9a\xe4\x6f\xd3\x24\x0b\x9a\x8c\x36\xa4\xf6\xb2\x45\x29\x8d\xeb\xd1\x7f\x47\x7e\x87\x16\xa5\x52\x65\x74\xa4\x44\x2b\x55\xb4\x4a\x07\xc3\x5d\x53\x47\x4a\xe8\x3f\xc9\xfe\xc1\xee\x8e\xd7\x6c\xee\x3f\xdc\xdd\xdb\xfd\x27\xa1\x3d\x79\xd1\x6e\xb3\xcb\x56\xea\xa7\x55\x0a\xe0\xcf\x75\x73\x4f\xb8\xc9\x64\x14\x29\xae\xb5\xc0\xf0\x62\x3d\x94\xee\x53\x0d\xf4\x95\xfc\xa6\xb2\xf4\x1b\x93\xd6\xec\xc3\xf7\x99\xfe\xa4\xb6\xe2\xb4\x3a\x15\x24\xd6\x72\x39\x62\x24\xad\xb7\x36\xed\x89\x8b\x76\x5b\x5e\xb6\x98\x5f\x8a\xc7\xde\x22\x97\x93\xb3\x6e\xe7\x9c\xfc\xcb\xc8\xd8\xfa\x7d\x3a\x3a\x8b\x82\x20\x0c\x82\xaf\x13\xcf\xb7\xfe\x43\xb8\x11\xef\xb3\xdb\xd3\x81\xe9\x5c\xb9\x0e\x54\xf1\xc1\x1a\x2c\x5b\x0b\x9b\x8b\x39\x87\x45\x0b\x95\xf0\x3d\xa2\x89\x7c\x55\x20\x20\xc5\xb7\x76\x0e\xbe\xc0\x90\x2e\xe3\x34\x5d\x55\x48\x4e\xd1\x00\xc9\xc3\x4e\x2e\xec\x1d\x5b\x72\x9d\x07\x5a\x0a\x69\x77\x0e\x11\xb3\x69\xd5\xca\x59\x2e\x7c\x30\x0c\xac\x45\x64\x55\xe4\xd0\x23\x45\xd7\x35\x47\x49\x7a\x1e\xf4\x73\x51\x6f\x1d\xa7\x54\x60\x1d\x60\x25\x58\x69\xc4\x5f\x82\xdb\x85\x81\xcf\x61\x98\x4b\x8e\xf1\xa6\xaa\xf7\xb4\xcc\x7d\xe5\xf3\x45\x46\xe8\x60\x6d\xbf\xeb\x8a\x2e\xc4\xa5\x1a\x9d\x80\xaf\x5f\x27\x19\x1c\x48\x0d\x99\xf0\xd5\xb2\x5d\x1d\x18\xd8\xe5\x7a\xf1\x6c\x19\x18\xd2\xcb\x4d\x42\xd5\xaa\x02\x40\x75\x91\x74\x65\x11\xcb\xdc\x58\x2b\x04\xa1\x2e\x46\xd7\x14\xb3\xec\x8a\x4b\x05\x21\xd6\x45\xe3\xb5\x45\x21\xda\x54\x18\xa2\xcb\x55\x9b\x8f\x14\x77\x79\xa1\xbe\x7a\xf5\xfa\xc3\xe9\x89\x3b\xa1\x22\x61\x5a\x30\x0b\xa9\x0c\xaf\x2c\x7b\xf3\xb6\x44\x33\x34\x96\xe0\x9c\x5f\x45\x49\x23\x4a\x1a\x3c\x96\x8d\x29\x1d\x45\xfd\x86\x2a\xb9\xd5\x70\x5a\xdc\x1d\xb3\x24\xa1\x43\x06\x0a\x81\x92\x8d\x46\x6a\x16\xf4\xb9\x35\xcd\xfa\x59\xed\xc9\x2c\xd2\xf8\xdd\x6d\x7c\x1f\xd2\x84\x35\x76\xfd\xcc\x3e\x10\xc4\xf1\x88\x51\xcb\x3c\x20\x7a\x13\x25\x2b\xfa\x63\x8e\x1c\xda\x78\x72\x7a\xfa\xc6\x51\x42\x9f\x2e\xb5\x93\x97\xe2\xe9\x38\x60\xa2\x54\xd2\x45\x4f\x83\xf3\xc6\xab\x93\x73\x05\xee\x23\x71\x48\xda\x3b\x9d\xbd\x87\x7b\x8f\x76\x0f\xf6\x1e\xce\xe7\xe5\xf3\x21\x11\xf3\x39\xf2\xe6\x02\x2b\x41\x04\x37\x9b\x68\x2b\x4a\x8e\x23\x1e\x49\xd5\x15\xf3\xb9\xf8\xf7\x0e\xae\xa3\xd3\x24\x19\x1a\xf6\x6a\x34\xac\x21\xfc\xf8\xcd\xe9\xd1\x79\x49\xf9\x41\x5e\xaa\xae\x36\xe6\xa5\x44\x23\xe2\x89\xa4\x3c\x54\x2f\x3f\x68\x20\xfd\xa5\xe5\x38\x39\xca\x0f\xe7\x67\xaf\x4e\x5e\x94\x38\x1f\xfb\x39\x6f\xcb\x6c\x2e\xaa\x00\x77\x43\x03\xaf\x5e\x96\xb0\xfb\x39\xac\xd5\x92\x87\xf9\x3b\x2d\x24\xb9\x51\x62\x84\x25\x81\x7b\x53\x6e\x2c\x17\xf0\x39\xaf\xfb\xcd\xab\x0f\x56\x6b\x1e\xfd\xba\xe4\x36\xcf\x8a\xf2\xc6\xd1\xd9\xd9\xd1\xd7\xb2\x70\xc7\xf3\x73\xfe\xd9\x5f\x69\x4f\x12\xa5\x15\x69\x3e\xdf\xca\x35\xf4\x9c\xbd\x66\x48\x4f\x9f\xbc\x7e\xfe\xf4\xbc\x31\x8b\xe4\x55\x83\x36\x06\x11\x1b\xf5\x1b\x9c\x8e\x59\xbf\xf1\x3f\x9d\x96\x6c\x39\xff\x53\x57\x68\xb8\x70\x3f\x23\xea\x42\x96\x16\xce\x98\x21\x86\x7b\xcc\xd7\x13\xfd\x4a\xaa\x15\xa4\x95\x1e\x43\x62\xc7\x57\xe4\x31\xbd\xc3\xd5\xdb\x58\x23\xa4\x6c\x5d\x34\x40\xa2\xd8\x65\x64\x05\xac\xf1\xe6\xf4\xe4\xc5\xf3\xb3\x06\xd5\xb8\x1a\x27\x8c\xf5\x1b\x7a\x33\x68\x68\x62\x1b\x41\x2a\x1b\x31\x1f\xdd\x35\x12\xc6\x1a\x4e\x2b\x47\xd3\x72\x1a\x8c\x4b\x11\xb1\x44\x57\xf0\x1b\x2d\x19\xd6\x5b\xb2\xe3\xff\xb2\x8b\x7f\xd1\x40\xd3\xd3\x45\x77\xa6\x40\x89\xd9\xe2\x52\x33\x30\xba\xd9\x57\x34\x39\x9d\xf1\x77\x22\x9e\x30\x21\xef\x50\x8a\xf1\xbd\x45\x6d\x7a\x69\x84\x05\x4d\x2a\xb6\x59\xcc\x95\x84\x34\xa3\x97\x92\x13\x74\x8a\xcc\x2f\x28\x65\xd7\x89\x44\x27\x12\x95\x0d\xda\xf5\x4b\xdd\x97\xbb\x03\x88\x09\x77\x87\x10\x11\xaf\x1b\x1d\xc6\xc5\x8e\xdc\x6a\x65\x04\xc4\x17\xd1\x65\x36\x38\xd5\xea\x59\x37\x24\x21\x52\x95\x59\x35\x85\x79\x2d\x7b\x7e\x49\x7e\xad\xa7\xf5\xeb\x2b\x5d\x52\xb1\x06\x96\x95\xd8\x2f\xe8\x1a\x90\x63\x08\x14\x55\xdd\xc0\x0d\xba\x01\x09\xdc\x20\x23\x26\x30\x26\x9d\x68\x80\x6a\xa4\x0c\xc8\x89\x42\x08\x83\x82\x18\xd5\x3b\xba\xe5\x03\x5c\x34\xdd\xaf\x31\x67\x63\x21\xca\xbe\x7a\xd6\x0a\xe7\xaa\x55\x96\xa7\x6d\xb3\x65\x7e\xa5\x6f\xe0\xde\xf4\xb0\x61\xe0\xda\x35\x90\xf5\x60\x58\x1d\xc0\xa1\x54\xdb\x8e\x1e\x40\xed\x4e\x08\x5d\x6a\xf5\xa7\x52\x12\x2c\x93\xf6\xb6\xed\xe5\x9c\xa1\x90\x41\x41\xc6\x0a\x9f\xa7\xf1\x3b\x95\xa5\xc7\x55\xc9\xa2\xd8\xa2\x9e\xdf\x4e\x58\x28\x23\x3e\x54\x9b\x92\xde\x8c\x4a\xb3\x3c\x2f\x0c\x76\xcb\x86\x6c\xee\x6e\xab\x1d\xa0\xb0\xe0\x6e\x75\xba\x4b\xfb\x94\xe7\x57\xbb\x9e\xbb\x54\xe1\x71\x69\x37\xdb\xc6\xb2\x7d\x29\xdb\x1a\x32\x5e\x5f\x61\xb9\x5b\x5e\x9d\x5d\xbb\xa1\xc6\x11\xe6\x6c\x38\xe3\xa9\xf9\x82\xcd\xc0\xae\x78\x61\x3e\x2e\x18\x67\x81\xa1\xaf\x31\xf4\x9b\xcd\x65\x28\x8b\x56\xa6\xa1\xd8\x2a\xa8\xdd\x12\x6a\xa0\xa1\x06\xcd\xe6\x50\x41\x0d\x41\xb8\xc3\x72\x19\x14\x50\x57\x1a\xea\x6a\x15\xae\x62\x73\xb1\x10\x58\xd3\x6f\xb8\x5e\x6a\xde\x2a\x45\xee\x72\x10\x2c\xf1\xb9\xcb\x0e\xa5\xf6\x63\xaa\xc9\xa7\x2a\xd6\x3e\xb5\x0b\x76\xb9\xce\xf8\x3f\x59\x2b\x88\x6a\x81\xc7\xec\xbe\xd1\xe0\x0e\x09\x50\x0c\x10\x38\x6e\x39\x8e\x2d\x18\xcf\xec\x19\xc8\x35\xce\xbb\x0d\x62\xab\x34\x7e\x4c\x99\xc9\xc1\xb7\x9c\x28\xb4\x25\xba\x1b\x0b\xdd\xfd\xb6\xef\x01\x55\x42\x73\xf1\xf9\xa8\xfa\xb9\x53\xfb\xfc\xa1\xfa\x79\x07\x02\x9f\x43\xe8\xab\x2a\x8c\x94\xfe\x7c\x83\x94\xbe\xab\xa1\xfb\x5a\xf0\x87\xeb\x0d\x80\x7b\x16\xa0\x6e\xc5\x53\x6e\x9b\xe4\x5f\x69\x22\xb8\xb6\x3c\x03\xf3\x9f\xf2\x56\x2b\x53\x15\x74\x0f\x5e\xf9\x17\x97\x8b\x9c\x43\x1e\x2b\x58\xe0\x65\x0b\x4e\xed\x15\xff\x81\x23\x7b\x99\x73\x74\xc3\xd1\x2b\x05\x80\xb1\xbd\xce\xbf\x67\x04\x72\xf7\xca\x28\x48\x02\x83\x46\xac\x9b\x7c\x5e\x69\x89\x3d\x16\x35\xf4\xdf\xcd\x57\x30\xd5\xe8\x2a\x4c\xf3\xbe\x70\xb2\xd5\x81\x33\xae\x34\xb3\xa2\x52\x5d\x81\xe2\x13\x67\x3c\x33\x64\x63\xd8\xfa\x92\x99\xbb\x55\x09\xaf\xcb\xc9\x19\x77\x93\xab\x68\x20\x11\xee\xe2\x2d\x3b\x70\x43\x3b\x74\x84\x3b\xc8\x34\x66\xae\xd6\x93\xbb\xad\xa6\xb8\x67\xdc\x62\x1d\xf5\x4f\x01\x37\x54\xba\xe7\x50\xb3\x1f\xde\xc5\xc2\x1d\x12\xf5\x33\xd2\x2c\x56\x2d\x1e\xd3\x20\x85\x50\x7f\x08\x90\x42\xa7\xb6\x9b\x1c\x72\xc1\x46\x09\x53\xd4\xea\xf8\x8e\xc2\xcd\xe0\x0e\xdc\x50\x57\x1d\x54\x7a\x42\xe1\xe1\xaa\x0b\xb5\x09\x22\x1a\xa0\x7d\x43\x4d\x46\x9e\x70\xaf\xaa\x6b\x30\xab\x78\xa0\x2b\xbe\xca\x9b\x8c\x75\xa5\x0d\x45\x83\x9a\x5d\xda\x06\xe9\xf9\x1d\xa5\x0a\x2a\x50\x88\x7c\xe1\x0e\x17\x90\x97\xed\x2f\x16\x0b\xc4\x71\x57\xf7\xf6\x62\xb1\x41\x9b\x3b\x51\x03\xc5\x80\xbb\xe1\x13\xf5\xe7\xa1\xfa\xb3\x53\x6e\x08\xcb\x61\x31\xf8\x7e\xb1\xa8\x38\xf0\x4e\x6a\x8a\x9c\xd9\xbb\x66\x68\xc4\x81\x83\xe8\x09\x77\x30\xa2\xc3\xc4\x9f\xc6\x51\xbf\xe1\xe1\xae\xde\xc5\xe6\xf3\x2b\x94\x59\x45\x63\x72\xbf\x80\x88\xa0\x90\x48\xa4\xb7\x32\xb5\x13\x13\x8a\x02\x88\xd4\xa6\xb8\x42\xf7\x07\xa6\xb9\x14\x53\x12\xd0\x1b\x9e\x1b\xa7\xde\x28\xf6\xd4\x4d\x5d\xda\x6c\x22\x24\x89\x9c\xcf\xef\x17\xf8\x82\x5d\x92\xd4\xa5\x48\xab\x49\xa0\x20\x56\x20\x64\xe4\x7e\xa8\x35\x6a\x43\xe2\x02\x52\xc2\xdd\x10\xa8\x92\x91\x41\xc9\x39\x4c\xcb\x39\x83\xc2\x3b\xe5\x5e\x91\x57\x1c\xcd\xd0\x73\x5e\x74\x54\xc3\x8e\x2a\xd2\x5f\x38\xdc\x6f\xfb\xfb\x10\xf8\xf6\x64\x30\xae\x1b\xee\xd2\x8a\x35\xd9\xdd\xee\xdd\x21\x0a\x4c\x33\x37\x3f\x6c\x36\xe3\xde\xad\x0e\xbb\x13\x6e\x04\xc2\xbd\x56\x6f\xef\xf4\x8b\xb0\x27\x5c\x35\xd4\xea\x95\x1a\x06\xe0\x6e\x80\xf1\x02\xd9\xe6\x35\xb9\x40\x31\x04\xd6\x00\x05\xa6\xa9\x6a\x4c\x18\x70\xd5\xad\x03\x14\x29\x59\x01\x04\x86\x9f\x1c\xc5\x10\xba\x01\xa4\x28\xc2\x05\x8e\xea\x5b\xa0\xbd\xfb\x49\x2c\x64\xe2\xd3\x85\x7f\x9f\x39\xb7\x38\xb9\x5f\xe8\x01\xfc\xfc\xbb\x3c\x41\xb8\x43\x54\x67\x09\x6b\xf6\x8b\x19\x3a\xe7\xc0\xdd\x2b\xc8\xd8\xb6\xa8\x4e\xb9\x67\x9b\x03\xb6\x34\x33\xbf\xf1\x05\x8c\x14\x43\x2f\x79\xdb\xeb\x3a\x47\x1f\xab\xef\xaa\x0d\x1f\x37\xb2\x72\xee\x73\x88\x6b\x36\x9c\x9f\xc5\x66\xa4\xa7\x10\xa4\xb9\xa3\x53\x4f\xcb\x97\x1c\x6d\x79\x20\x20\xd5\x1b\x1d\x06\xf5\xbb\x03\xb2\xf8\xcd\xf1\xf7\x6c\x3f\xbd\xdf\xf6\x9d\xc1\xad\x03\xd4\x4f\x2f\xd8\xe5\x7c\x7e\x1f\xf9\xc7\x70\xed\x1f\x57\x02\xcb\x5e\x5a\xeb\x36\x93\x92\x44\x21\x25\x75\x7c\xb3\x00\x84\x7b\x03\x94\x20\x4a\x52\x88\x09\x83\x19\xe2\xbd\x37\xfc\x82\x5e\xba\xcc\x37\xff\x0e\x2a\x72\x5e\xe9\x49\x8c\xbb\x42\x7b\xab\x7e\x60\xc5\x3a\x27\x8a\x6f\x14\x5b\xb0\x92\x11\x4b\x6f\x94\x5a\x20\x48\x5e\xa4\x97\xaa\x1a\x0a\x29\x41\xa9\xb6\x35\x63\x8b\x6e\xe0\xbd\xd4\x8d\xc8\x09\xa2\x90\xba\x11\xf6\x53\xf7\x3a\xfb\x71\x8d\x21\xc5\x85\x31\xa1\x54\x24\x84\x3b\xee\x86\x6e\xa0\x54\x02\x37\xc0\xba\xad\x6a\x72\xaa\xd6\x66\x15\x77\x2b\x66\x0b\x4d\x46\xd6\x27\x6e\x0c\x12\xee\x27\xbe\x70\x39\xfc\xf0\xd9\xc2\x6c\x53\x14\xe2\xb2\xf3\xde\xea\xe6\xbe\xe1\x17\xfc\xb2\xd9\xbc\x42\xbb\x56\xbf\x7e\xaa\xce\x3a\x0d\x09\x1a\x92\xdc\x33\xff\x1b\x07\xe1\x0b\xa0\xfe\x0f\xbe\x80\x67\xc5\x1e\xf8\x6d\xad\x94\x53\x89\x5a\xf9\x51\x2c\x78\x09\x21\xb9\xb8\x84\x98\x68\xcc\xae\x50\xdc\x4e\x12\x0f\x6a\xcb\xc3\x0c\x46\xc2\xe4\x79\x34\x66\x71\x6a\xf1\xec\x7c\xb7\xc6\x78\x01\xb2\x18\x0c\xeb\x73\x38\x62\x54\xe4\xc5\x84\xb6\x07\xe5\x50\xa6\xce\x80\x44\xa6\x5d\x6e\xb8\xc6\xec\xdf\x15\xb9\xcf\x12\x97\x22\x60\x08\x29\x89\x91\xd0\x3a\xa1\x51\x4f\x72\xf9\x91\xea\xa8\x28\x7a\x89\xca\x38\xb9\x68\x81\xe1\x3e\x49\x83\x24\x14\x51\xc0\x2a\x6c\x2f\xcc\x77\xf5\x05\xa4\x7c\x35\x08\xe2\x6a\x0b\x08\x33\x83\x3d\xc6\x96\x69\x19\x1f\x7a\xf3\x79\xa8\xfd\x02\xda\x96\xdf\xc1\x0b\xb3\x6a\x9f\xf0\xee\x1a\xce\xb3\x4a\xa1\xd1\xae\x50\x9c\x8b\x59\xef\x39\x71\x52\xde\x67\x83\x88\xb3\x7e\xa9\x9b\xf7\xe3\x30\x1d\x33\x2e\x7b\xf9\x83\x7f\x6f\x39\xfc\xdf\x15\xc2\x11\x9d\x4c\x18\xef\x3f\xbd\x8a\x46\x7d\xd5\xe1\xab\x36\x58\x46\x98\xcb\xe3\x3e\x2b\xb7\x8d\x09\x15\x8c\xcb\x93\xb8\xcf\x5c\xc1\x26\x23\x1a\x32\x83\x60\x2a\x10\xb7\xb7\xdc\x05\x06\x86\xe1\xbe\xc2\x6f\xfe\x5c\x29\xcb\xaa\x96\xbc\xa8\xcc\x47\xdb\x2c\xfa\x0b\x1f\x98\x67\x8d\xf9\x7d\xce\x43\x68\x97\xb5\x48\xea\x06\xf3\xb9\x07\x99\x2b\x2b\x2d\x3d\x6c\xad\xd2\x49\xa5\x99\x6c\xe8\x87\xd0\xf7\x47\x42\x87\x3f\xfa\x12\x06\x3e\x85\xc0\x67\x5a\x42\x40\xd9\x8e\x0f\x5f\xff\x5b\x08\xfc\x3d\x12\x77\x7e\x8b\x44\xe3\x99\x11\x9b\xa4\xf4\x6b\x9f\xeb\x2d\x25\xf0\x3b\x2d\x24\x74\xe5\xb8\x32\x40\x42\xd4\xca\xec\xab\xed\x07\xc6\xbe\x80\x9b\x5c\xb2\x58\xac\x63\x1c\x02\x5d\x70\x10\x97\x2b\xe4\x2e\x23\x37\x66\x93\x56\x8a\xf5\xca\x50\x86\x03\xe4\x2a\x2c\x79\x64\xf2\x42\x5b\xe0\x05\xd9\x20\x10\x16\x78\x80\xad\xc2\x54\x46\x2c\x6b\x5c\xa9\x20\x68\xa3\x03\xc0\x42\x07\xe9\x2a\x84\x76\x24\xf3\xe2\x37\x1c\x04\x15\x84\x40\x57\xa1\xac\x06\x37\x2f\x7e\xcb\x85\x50\x43\x0b\xe1\x2a\xc4\xf5\x70\xe7\xc5\x6f\xba\x19\x96\x90\x43\xbc\x0a\xfd\x72\xfc\xf3\xa2\xe6\x8c\x18\x40\x00\x09\x8c\xa0\x0f\x53\xd8\x86\x31\x5c\x55\xaa\x58\xfa\xba\xaa\x12\x41\x02\x90\x24\x01\x46\x46\x90\x92\x3e\x50\x32\x85\x90\x6c\x43\x4c\xc6\x10\x91\x2b\x78\x44\x08\x41\x9c\x0c\xf0\xaa\x70\x6b\x88\xd6\x05\x5c\xa3\x28\x5b\x45\x75\x77\xc9\x62\x7d\x50\x88\x92\x7d\xa8\xe7\x58\xf2\x15\x06\xba\x61\x15\x3a\xb4\x63\x03\x43\xb8\x11\x76\xa7\x02\x1b\x6f\x84\xdd\xb5\x61\xbb\xeb\xd6\x98\x06\xdd\x53\xa0\x02\x62\xff\x7e\xa0\x4b\xc8\x45\x85\x0d\x44\xa2\xe4\xd3\x8e\xda\xe7\x26\xd2\x51\xca\x9a\x33\x71\x7c\xbe\x66\xfd\xab\x4e\xd0\xaa\xe0\x76\x6f\x86\x52\x01\x4a\x98\x41\x92\x70\xe0\x24\x61\xda\x77\x19\x63\xc5\xcc\x98\xbb\xad\xd8\x7e\xef\x0e\x0d\x18\xf0\xc3\xdd\x5e\x20\xfc\x44\x40\xc0\x94\x58\xcd\x5c\x8a\xfd\x19\x8a\x58\x66\x83\x5e\x60\xec\x67\xa1\x6f\xc0\x72\x4f\xa1\x80\x60\x5d\x3f\x34\x4e\x11\x37\x5b\xbd\x62\xb7\x0b\x0c\xc9\xda\x1e\x0b\x5f\xab\x49\xe0\x86\xaf\x31\xd0\x23\x5f\xb8\xf4\x08\x68\xaa\xfe\x4d\x2b\x5d\xa1\x79\xae\x25\x67\xde\x2f\xac\x88\xb5\xc2\x20\x45\x81\x11\xe9\x6e\x43\x4a\xa4\xcb\x75\x74\x41\xdc\x55\x83\xb7\x45\x08\xeb\x21\x49\x84\x16\x8b\x91\xfa\x87\xa8\x9d\x51\x0d\x16\x21\x84\x35\x9b\x4e\x38\xa2\x49\xa2\x7e\xa4\xbd\xbe\x40\xd2\x1c\x56\xd0\xe2\x29\xc5\xbe\xf9\x7a\x42\xc7\xac\x80\x10\x06\x42\x68\x88\xc5\x72\x84\x5d\x5f\x54\x64\x7a\xc2\x2f\xc4\x65\x57\xfd\x21\xac\xc7\x5a\x4e\xc3\x69\x49\xdf\x3a\xae\x36\x15\x55\xd3\xda\x76\xae\xdd\x17\xee\x07\x05\xe1\xde\xe8\xe0\xd1\x1b\xc2\x5d\x13\xda\x8c\x73\xcb\x44\x01\xf6\x9e\xbb\xa1\x60\x54\xb2\x73\x76\xab\xc5\x03\x13\xc8\x17\x0d\xd0\x9e\x06\xb3\x2c\xc7\xdc\xbd\xd1\xea\xe9\x75\x57\x7d\x62\xee\x76\x17\x2f\xf9\x17\xd2\x5e\x4a\x2e\x52\x60\xee\xf5\xa5\x9f\x7b\xb9\x95\xf0\xad\x04\x92\x1b\xe3\xda\x26\xf7\xd7\x7e\x0a\x13\x5f\xe4\xc6\x23\x14\x92\xa9\x40\x0c\x94\xfe\xcd\x46\xe3\xef\x6c\xca\xb8\xfc\xae\xc4\x97\xef\x82\x0d\x08\x85\x70\x11\x0d\xd0\xae\x4d\xf5\xb6\x40\x4a\x39\xbe\x42\xdc\x1d\x62\x10\xc0\xdd\x3e\x86\xb0\x5b\x38\x07\x7a\x45\xb3\x9e\x8f\x98\x12\xa5\x4e\x3e\x20\xee\x0e\x40\x3b\xc9\xea\xdf\xb4\xeb\xac\xfb\x84\x37\x9b\x0e\x55\xeb\xc5\x0d\x9b\xcd\xd0\xa5\xfd\xfe\x73\x45\xc8\x9b\x28\x91\x8c\x33\x81\x9c\x70\x14\x85\x37\x0e\x3c\xe1\x28\xc4\x18\x14\x09\x59\xcd\x85\xe1\x32\xd6\x0a\xfb\x0a\x97\xc4\x3b\x8e\x42\x98\x0a\xd4\x51\x8d\xe8\xc5\x17\xd1\xa5\xaf\xfe\x68\x27\x43\x21\xc4\x86\x96\xbd\x5c\x2c\x19\xee\x95\x6a\x27\xed\x68\x98\xae\x62\x49\x6a\x20\x7a\x2b\xed\x14\x84\xbb\x89\xbc\x1b\xb1\x95\xc1\xae\x0b\xc4\x21\xc5\x7e\xb6\xf8\xab\x18\x6c\xbd\x92\xab\x01\x39\x4e\xf4\x2c\xd2\x4f\x6a\x19\x94\xaa\xa6\x2c\xa3\x84\xd8\x25\x84\x44\xa9\x91\x6a\xea\x50\x6d\x62\x0a\xcd\x5f\xf7\x87\xbb\x4d\x08\xa1\x5a\x69\x74\x7f\x10\xda\x0d\x63\x2e\x23\x9e\xb2\x05\x77\x05\x1b\xc7\x53\x56\xed\x68\xa6\x76\xb7\xb0\x34\x96\x44\xa0\x96\xb2\x75\xec\x27\xd7\x57\x06\xee\x0f\x90\xa4\xaf\x59\x07\xf0\xdc\xbd\x22\xb1\xd5\x6b\x90\x12\xed\xe8\x06\x41\xa4\x4b\x81\x92\xb4\x97\x1e\xee\xf6\x84\x4b\x7d\xc5\x44\x7c\x01\x92\x74\xd4\x12\x15\x6e\xe0\xef\x12\x92\x36\x9b\x9a\xa7\x84\x04\xc9\x66\x53\x75\x61\x3c\x79\x27\xe2\x09\x1d\x52\xb3\x95\x01\xda\x59\x02\x4f\xb1\x02\x9d\x08\x3d\x71\x9f\xb1\x01\x4d\x47\x12\x61\x88\x70\x97\x91\xd0\xbd\xee\x9a\xb8\xe1\xe5\x80\x78\x86\x29\x61\x88\xe2\xae\xb6\xaf\x95\x93\xa8\xd0\x74\xe2\x76\xbb\xab\x60\x2e\xe2\x4b\x05\xa6\x74\x94\xc9\x22\x44\x54\x5b\x60\x72\xb9\xc0\xfd\x41\x38\x0c\x16\x48\x00\xc5\xc0\x97\xe7\x2d\x83\x10\x06\xa2\xd9\xbc\x9f\xd0\x24\x89\xa6\xcc\x4f\x54\x9d\x87\x3b\x4a\x32\x51\x8c\x2d\x34\xe6\xbd\xf5\x63\x61\xc0\x72\x31\x52\x4f\x11\x3d\x77\x76\x57\xcd\xbe\x42\x8c\x36\x33\xce\x8a\x23\xea\xb2\x1e\x77\x13\x26\x8f\xa4\x14\x51\x90\x4a\x86\xcc\x09\xb3\xac\x5e\xeb\x35\x5e\x14\xf3\x73\xef\xef\xd5\x01\x29\x61\xee\x40\x73\x9b\x78\xa9\xbe\x93\x0f\x28\x85\xd5\x75\x9a\x4f\x65\xbd\x53\x3a\x4a\x59\xc1\xea\xaf\x58\x78\xc3\xfa\xd9\x4f\x6d\xc8\x23\x24\x55\x6b\x42\x9b\xf8\xf0\x62\x21\xc5\xdd\xfd\x2c\xe2\xfd\x78\xb6\x82\x6d\x48\xc7\x78\x1c\x4e\x35\xab\x74\x8d\xda\x57\x38\x4c\xef\x17\xe0\x64\x03\xe3\xc0\xfd\x90\x49\xdf\x12\x9b\x06\x82\x6c\x79\x4a\x34\x29\xc3\x34\x2c\xaf\x58\x65\x0b\xb8\x28\x02\xd8\x87\x19\xef\x00\x0f\xdb\x07\x9c\xaf\x84\xad\x1e\xde\x6f\xfb\x02\x84\x2f\x21\xf1\x19\xc8\x4c\x47\x80\x34\x57\x16\x0a\x23\x4c\x19\xa8\x64\xb9\x75\x44\xe5\x28\x89\x0e\xeb\xcc\x19\x13\x57\x62\x82\x92\x26\xd4\x62\x4c\xb7\x08\x31\xac\xa0\xb3\xa5\x7b\x6c\x47\xbf\xb0\x2d\x29\x57\x6a\xef\xf4\x80\x69\x67\x2b\x59\x6d\x23\x52\x3c\xf5\x37\xcf\x49\xa9\xed\xb5\x38\xed\x96\x69\x89\xdc\x55\x4a\x18\x77\xfb\xc0\x7c\x06\x03\x5f\xed\x03\x81\xcf\xdd\x60\xb1\x50\x8c\x81\x92\xce\x22\xb3\x6b\xd1\xcc\xaa\xb5\x5f\xf1\x34\x8f\x20\x56\x95\x43\x44\xc2\xc2\x67\x49\x22\x42\x48\xc1\xe1\x07\xcd\x66\xa4\x56\xea\x80\x84\x17\x91\x9a\x1c\x8a\xb7\xab\x0e\x18\xd8\x6d\x45\x42\x6f\xc4\x37\xb8\xab\x1e\x84\xda\x91\xf5\x86\x15\xd4\xc6\xce\xbd\x01\xe1\xde\x40\xa0\xc6\x4f\x97\xf3\x0e\x83\x22\x72\x4d\xf7\x57\x07\x18\x04\xb8\x08\x4b\xc9\x89\x4d\xd4\xde\x0c\x23\x22\xdc\x6b\xe8\x93\xad\x0e\x4c\x55\x75\x7a\xb3\x9e\xaa\xcd\xba\x4f\xb6\x3c\x58\xda\xb1\x93\x5e\x42\x2e\x12\x98\xaa\x1d\x3b\xc9\x22\xc3\xd5\x8e\x3d\x25\x53\xf7\xa6\xd8\xd9\xb6\x89\xc8\x50\x6d\xaf\x47\x35\xea\x8d\xc8\xc5\x08\xb6\x15\xaa\x91\x41\xb5\xad\x50\x6d\x93\x6d\xf7\x26\x6f\x62\xbf\xd9\x4c\xb2\xe6\x6c\x11\x32\xca\x1e\x7b\xf5\xd9\xe0\x23\xd4\x5f\xb7\xec\x89\xd7\x95\x87\xe5\xf1\x05\xe3\x25\xe4\x17\xf2\x52\xcd\xc4\x0b\x79\xb9\xc2\x45\x88\x12\x18\x61\x3f\x21\x84\x8c\xf0\x7c\xae\xeb\xd9\x01\x06\x23\xd3\xc5\xaa\xdf\x95\xda\x22\x81\xb5\x3a\x4b\x7e\x75\x3d\x08\xdc\xa5\xda\x67\x49\xb3\x31\xd8\xd5\x26\x72\xba\xe4\xa2\xd7\xe8\x26\xc5\x0a\x81\xbb\x7a\x08\xd3\x12\xc4\x6d\x0e\xb1\xeb\x6b\xdf\xf4\x95\xae\xe7\x6a\xed\x32\x09\xc8\x4c\xcd\x92\x3e\x08\x25\x7a\x04\x19\x3d\x7b\x7a\x4e\x74\x03\x22\xdc\xa8\x74\xe6\xda\x2d\xc8\x21\xf7\xcd\xec\xb1\x8d\xd3\x16\x35\x69\xb6\xa5\x77\x0b\x67\xb5\xda\xdb\x32\x4f\x71\x0f\x21\x6a\xd7\x8e\xad\xca\xa9\x52\x74\x73\xbe\x80\x7d\x8b\x62\xeb\x90\xb2\xa8\x09\x18\xb9\xa2\x56\x86\x95\x70\xac\xc4\x9a\x2d\xbd\xb5\x2a\xf1\x24\x7f\xda\x2d\x9e\xf6\xf4\x53\xcf\x04\xa1\xf4\x50\x4c\xf8\x45\x7a\x89\x95\xe6\x68\x22\xa8\x71\xb3\x99\xf1\xef\xac\x44\xce\xbf\x0d\x0f\xca\x64\x1e\xd9\x6c\x22\x14\x92\x18\x2b\xe1\x04\xc5\x84\x62\x77\x5b\xbb\xb8\x43\x97\x42\x9c\x9d\xe4\x42\x8c\x30\xe3\xcb\x31\x72\x7d\xe5\xb7\xec\x65\x02\x98\xec\x39\x4e\x2e\x4a\x49\x55\xc1\xae\x79\x6b\x78\xa9\xd6\xd5\x14\x5b\x1a\x40\x9c\xb3\x57\x7f\xf9\x10\xd1\x45\x7a\xa9\xd0\xa8\x9d\xc2\xcf\x3a\x39\x3f\xf5\xa6\x6a\x84\x54\x75\x76\x9d\x20\xdd\x6d\x51\x16\x8d\xa3\x7b\xaf\x42\x74\xa4\x18\x62\x64\x1f\x1b\x2d\x0f\x7f\x5b\x3c\x3c\xe7\xdc\x4c\x73\x6e\x06\x9c\xa4\x39\xa3\x13\x84\xe6\xcb\x4c\x1c\xf2\x9e\x1e\xd4\x03\x60\x70\x3f\xf5\x05\x44\xbe\x3e\x37\xe1\xf3\x43\x91\xcd\x83\x87\xe6\x13\x07\xe6\xd3\x45\x29\x16\x87\x84\x1f\x8a\x9e\xd6\x5c\x89\xd7\x8d\x0f\xc3\x6e\x9c\x07\x9a\x44\x24\xbd\x88\x2f\xbb\x43\x81\x22\xa0\x17\xf1\x25\x48\x68\xb5\x4c\x5c\x6c\xa4\x0d\x5d\xd6\x2c\xbd\x15\xab\xcf\xfa\x00\x25\xf7\x8b\xdc\xce\x6d\x04\x70\xd5\x8c\x41\xc1\xa0\x21\x20\x51\xfe\x98\x10\x0f\x46\xc4\x83\x3e\x61\xdd\xe4\x70\xd0\x6c\x8e\x0e\x83\xcc\x79\x3b\x85\x6d\x82\xa6\x24\xbe\x48\x2e\xb1\x4b\x61\x4c\xd0\x35\x89\x2e\x46\xfa\xc7\x15\x99\xba\x01\x0c\xc9\xb5\x1b\x28\xc6\xbe\xbd\x45\xc8\xd8\x94\x9a\xc0\x0c\xee\xe0\x16\x6e\xe0\x08\x3e\xa8\xc2\xad\xce\x25\x3c\x57\x05\x5b\x1d\xbd\x09\x7c\x68\x36\xd1\x8c\x7c\x70\x03\xb8\x23\x63\x35\x4d\x27\xe4\x83\x9a\x5f\xf0\xbc\xd9\x44\x37\xe4\xb9\x1b\xc0\x11\x51\x12\x32\xba\x25\xcf\xf5\x87\xa3\x66\xf3\x0e\x0f\x05\xba\x82\x1b\x48\xa1\xd5\xea\x63\x38\x12\x3a\xd7\xc4\x36\x0c\x61\xa4\x44\xb2\x7e\x8b\x5c\x19\x2b\xe4\x87\xfc\xcb\xcc\x40\xf6\x5b\x64\x66\xbe\x24\x2d\xb2\x03\xa3\x16\xd9\x31\xf2\x65\x34\x40\x47\xb8\xdf\x6a\xe5\xb8\xc6\x39\xae\xa2\xa6\xbe\x8d\x37\x69\x91\x4e\xb5\xf4\x1d\x2e\xea\xba\x2a\xea\xca\xa0\x87\x02\xcd\x60\x98\x53\xbb\x4c\x43\xa7\x9b\x3b\xae\xb7\x3e\xcc\xe7\x93\x2d\x42\x6e\x71\x20\x18\xbd\xe9\xd6\x71\xd6\xa9\xab\xd5\x71\xb3\xbe\x8e\x9d\x85\x91\x64\x75\x7b\x6c\x5a\x8a\x16\xb5\x60\xd4\x6a\x2d\xb4\xcb\x21\x39\x1c\x74\xf3\xf6\x58\x83\x6e\xc6\x79\xb9\xa0\x39\xb9\x59\xce\x95\x6b\x78\x4a\x9e\xce\xe7\x17\x97\xdd\x8c\x5e\x6b\xae\x5c\xbb\x01\x64\x02\xd5\x53\xac\x6b\x44\xde\x61\xbe\xa4\xe6\x73\xef\x30\x2c\x9e\x9f\xe6\x1c\xf4\x91\x5a\x39\x33\x3f\x85\x5b\x3f\x84\x3b\xff\x69\xe6\x4c\xba\x11\xc4\xf9\xce\x46\xe3\xcf\x07\x4f\xde\x58\x39\x6d\x8e\xc4\x2a\xb7\xb7\x3e\xda\xa8\x7a\x38\xcc\xf7\x8e\xec\xbc\xd9\xbd\xf0\x53\x38\xf2\x43\x72\x1f\xfa\x1e\xfc\xf4\x19\xa8\x17\x49\x61\x19\xce\xe4\x0c\x55\x9e\x84\x5a\x8d\x52\x7a\x6a\xe8\x86\xf8\xbe\x86\x61\x81\x21\x74\x43\xb2\x93\x79\xcf\x2b\x82\x4b\xe8\xfe\x04\x06\x31\x84\xae\x50\x50\x82\xa4\x06\x6d\xe8\x26\x6e\x42\xee\x67\x7e\x6c\x30\x2c\x72\xea\x5b\x37\x22\x37\x93\x96\x81\x2f\xcb\x3b\x51\xd1\x2e\x5a\x04\x2e\x50\x43\x5a\x4e\x48\x58\x25\x84\x01\x75\x7f\x42\x08\x69\xb6\xb9\x5f\x09\x24\xe0\x31\xa4\xaa\x83\x43\x38\x52\xac\x69\xf1\xa1\x4a\x83\x09\x71\xb8\x17\xa4\x80\xcd\xad\xf3\xba\x53\xee\x43\xbf\x63\xf5\x9b\xb0\xf7\xce\xe7\x16\x57\xda\xb2\x5c\xf2\x35\x6b\xac\x61\x76\x4a\x48\x35\xd6\x30\x12\xb9\xc2\x4c\x2a\xb5\xb7\xd2\x6c\x5a\x05\x90\x90\xc8\x08\xcf\x6a\x08\x92\xde\x73\x45\x8f\x74\x6f\x20\x72\x13\x88\xb1\xff\x48\xbf\x45\x91\x2b\x89\x80\xc8\x4d\x49\x0c\xde\x21\x52\xfc\x2d\x71\x67\xb8\x10\x13\x4d\xf5\x01\x78\x59\xf5\xd8\x7f\xbc\x5c\x10\xa9\xba\x12\xb5\xad\x24\xee\x91\x9b\x10\x61\x50\x6d\x46\x84\x7d\x1b\x07\x86\x2d\xa4\x5a\xd5\x6a\x69\x47\x2c\xd2\xcd\xc2\xff\x2c\x26\x60\xaa\x67\xf1\x88\x48\xd3\xa6\x3d\x2d\x7f\x15\xcc\xbb\x4f\x64\x26\x54\xf6\x8d\x50\xd9\x2f\xc5\x44\x55\x71\xdf\x74\x60\xab\x03\x21\x88\x15\xa6\x21\xb3\x46\xa6\x44\xba\xac\x9b\x0b\xa9\xe1\x55\x34\xea\x9f\xc4\x7d\x96\x14\xdb\xcf\x98\x78\xdd\xf1\xe1\x34\xdf\xc8\xc6\xf9\xde\x73\xa5\x34\x7f\x32\xea\x4d\x2f\xc6\x97\xbe\xfa\xa3\x39\x7c\xab\x45\x5b\xc8\x2c\x7c\xbd\x14\xe8\x21\x19\x34\x9b\x83\x43\x32\x6c\x36\x51\x4a\x38\xda\xbe\x18\x5f\xc2\x55\x36\xb6\x43\x28\xfa\xa0\xd6\x03\x45\x17\x74\x29\x19\x2e\x8a\xfe\xc8\x75\x33\xf0\x40\xb8\x01\xd8\x79\x55\xae\xc5\x92\x43\x44\x9b\xea\x72\x11\x99\xfb\xc8\x9a\x6c\xf0\x54\x3d\x4b\x3b\xe8\xf1\xa9\x58\x25\x28\x0b\x5b\x50\xae\xeb\xca\x12\x58\x2d\x2a\x65\xc9\xc7\x5f\xc8\xc1\x2b\x8d\x44\x84\x5b\xae\x45\x90\x64\xaa\x27\x2c\xee\xca\x15\xe3\x35\x9f\xa3\x55\xaf\x8d\x95\xa9\x3e\xb6\x5d\xd6\x6c\xca\x2d\x42\x78\xb3\x59\x73\x59\x4a\xe0\xd6\xe9\x68\xed\x89\x4f\x40\xb8\x69\x2d\x4e\x3f\x33\xa2\xb9\xa9\xfa\x8e\xa1\xee\xc8\xe7\x39\xd2\x67\x54\x52\xe4\x01\x2f\x64\x1e\x0b\xba\x10\xeb\x4d\xd7\xba\x49\x5d\x98\x5f\x45\x7a\x6f\xd5\x4b\xf7\x9a\x08\x37\xf1\x57\x7d\x22\xf7\xd7\xbe\x6a\xc2\xc4\x17\x6e\xba\xc8\xab\x3e\xf0\xed\xb3\x59\x49\x96\xe1\x45\xba\x91\x0e\x8b\xcc\x2d\x18\xa6\x47\xb8\x35\xed\x2f\xa4\x3b\x2d\x45\x3e\x9e\x87\x9a\x96\x02\x13\xd2\xf8\xb0\x16\xf7\x2a\x05\x19\x51\x45\xbb\xac\xd8\xab\xb2\x9a\x22\x9e\x30\x21\x9f\xb0\x41\x2c\x18\x9a\x0a\x94\xea\x58\x4c\x37\xc5\x40\xeb\xf5\x3c\x56\x2a\xcc\x56\x56\x03\x2e\x8d\x08\xb6\xf3\xd9\x22\x5b\xf5\xb3\x61\xe0\xd2\x3d\xb2\x95\x95\x86\xb7\xa5\x36\x20\xa1\xed\x6a\x6b\x0b\x87\x6e\x42\xcc\x2a\x70\x67\xc5\x90\x3d\x5a\x35\x5d\x73\x2b\x89\xe9\xc8\xea\x97\x68\x60\x9b\x1b\x24\x29\xcc\xc3\xcf\x32\x37\xfc\xb1\xa0\x43\x6d\x27\x2e\xd2\xec\xd8\xfd\x93\x8b\xcf\x17\xec\xd2\x3d\xea\xbe\xe3\x4a\xb3\x24\x84\xa4\x6e\xd8\x4b\xdd\xc4\x57\xfd\xe5\xfe\xd4\xdd\x65\x45\x49\x2d\x90\x74\xef\x4c\x3e\x80\xa2\x01\x65\x52\x0c\x22\xdd\xdb\x2c\xe8\x21\xb5\x83\x1e\xb2\x7d\x3e\xbd\xa0\x4a\xd2\x0d\xdd\x23\x88\xc9\x8e\x36\x44\x84\xbd\xd8\xd4\x15\x67\x75\x75\x6b\xc3\x16\x43\x65\xa8\x43\x57\x5c\xe2\x05\x6b\x36\x75\x54\x01\xb3\x82\x6e\x4c\xca\x86\xea\xd1\x11\xe1\x26\x88\xe3\x6e\xdf\x58\x36\xfd\x2b\xd4\xf1\xf0\x62\x81\x52\x9d\x89\x84\xe8\x25\x8a\x38\x61\x45\xfb\xac\x30\xd0\x57\x22\x8b\xae\x34\xb9\xa5\xd4\x94\x3f\xbf\x9b\xb0\x7c\x6a\xfc\xc9\x11\x77\x25\xbb\x95\x4f\x63\x2e\x19\x37\x47\x0b\x3b\x5b\x6b\x40\x1d\xa7\xec\xa4\x3c\x87\x01\xcd\x4d\x78\x09\xd4\x4f\x8e\x5a\x07\x47\x05\x39\x41\x33\x14\x0b\x48\x5d\x4e\xc7\x0c\x52\x57\x6b\x88\xda\x23\x52\x1e\xe6\xe7\xae\xa4\xc3\x13\x3a\x66\xae\x8c\xdf\xc4\x33\x26\x9e\xd2\x84\x21\x0c\x21\x39\xd6\x9a\x45\xd9\x81\xc0\x4a\xeb\x8f\xae\x2b\x24\x27\xe8\x95\x40\xf1\x05\xbb\xc4\x10\x16\xfd\x79\x87\x5e\xe8\x13\xb0\x10\x56\xe2\x34\x04\x70\x90\x96\x03\x58\x87\x31\xea\x14\x21\x4f\xd4\x9f\x87\xea\x8f\x15\x08\xa9\x0f\xca\xe7\xd1\xfb\xe1\x63\x48\x49\xa8\xbb\x07\x28\x79\x25\xac\x28\x98\xf3\x4a\x2c\x47\x61\x26\x67\x7a\xa1\x91\xb1\x12\x54\x85\x1a\xb1\x6b\x81\xd4\xde\xa5\x76\x0f\xa5\xf2\x2d\x4a\x27\xff\x69\xc5\x3d\x6f\xc8\x64\x55\x32\xd9\x5a\x32\x19\x70\x2b\x54\x62\xa6\x4d\xe3\x33\x73\xbc\x40\x93\x1d\xaa\xa5\x25\x23\x39\x62\x10\xab\xc7\x20\xee\xdf\x41\xa4\x9a\x10\xaf\x6f\xc2\x13\x4e\xd2\xae\x69\x07\xd5\xe9\x04\xc8\x0b\x8e\x1c\x55\xd4\xc1\xe8\x18\x23\xe1\x06\x8f\xb2\xd6\x45\x6a\xdf\x89\x55\xeb\x62\x88\x40\x4d\x6b\x88\x88\x84\x27\x9c\x78\x10\x6a\xa3\x4a\xb8\xd7\x6c\xa2\x9c\x08\xa2\x4f\x5a\xef\x61\xd3\x7c\xf8\x2e\x56\x06\xe5\x08\xf6\x23\x65\x89\x3c\xe2\xd1\x58\x7b\x00\x8e\x05\x1d\xb3\xde\xca\xb7\x95\x98\x22\x2b\x96\x8a\x43\x87\xed\x3e\x38\xf0\xb0\x15\xcd\x73\x2e\x90\xb1\xc4\x22\x99\x9d\xae\xb1\x23\xaf\x29\xc2\xf7\xa9\x96\x4e\xd2\x9e\xe7\xa3\xef\x02\x51\x0c\xda\xd3\xda\x29\x16\x59\xed\x94\x1f\xe1\x20\x7a\x48\xc3\x68\xf6\xa3\x85\x95\x8e\x12\xd7\x3c\xf3\xd3\x20\x49\xc9\x8e\x1d\xa1\xff\x45\x94\xce\xf9\xe7\x4c\x75\xcd\x28\x0e\x75\x8b\xdc\x2b\xb5\x09\xbb\x74\x3e\xbf\x42\x1d\xbc\x58\x1b\x2b\x49\x63\xb8\x66\x95\x70\x32\x7c\x2f\x9a\xcd\xab\x28\x91\xb1\xb8\x73\x87\x31\x12\x18\x38\x32\x19\x20\x74\x4b\xcf\xd6\x7a\x81\x57\x63\xcb\x51\x29\x45\xe4\x83\xa4\x92\x69\x9b\xb9\x03\x16\x5e\x38\x16\x6b\xb3\x33\x6c\x46\x9a\xc9\x00\xeb\xf0\xde\xd7\xcd\xf9\xb6\x75\x7e\x01\x2b\x3c\x26\x7e\x35\x58\x19\x4e\x56\x4f\x2b\xe3\x2d\xe8\x99\x7f\xfc\x63\x61\xfb\xfd\xab\x41\x2c\xa7\x1c\xd5\x82\xf5\xec\xd4\xa6\xf8\xfe\x15\x47\xa9\x0e\x2e\x2b\xf3\x9b\x2e\x7b\x80\x44\xd5\x03\xa4\x4f\x62\x5b\x84\xca\x35\xbe\x1f\x13\xce\xb7\x2a\x86\x22\x3b\x1f\x64\x9f\x90\x12\xb8\x77\x2b\xb5\x17\xdf\xbf\x91\xb6\x2f\xfe\x4d\x36\xd7\x57\x44\xe6\x0a\x7c\xff\x5d\xd8\xe3\x62\x82\xe8\xf3\x00\x38\x77\xc8\x64\xe6\xa4\x7d\x72\xf7\xaa\xaf\xd6\x8a\x40\xbc\x77\xc3\x91\xe2\x69\xd8\x3f\xe2\x68\xa4\x1d\x7e\x66\x11\xeb\x88\x60\x51\x8d\x08\x2e\x83\xf0\xde\xd4\x59\x4b\xbe\x5b\x5d\x88\x4b\x84\xe1\xd5\xa6\x98\x60\x49\x96\x83\x59\x4e\x84\x9b\x84\x22\x1e\x8d\x34\x24\xbc\x5a\xd4\x83\x2a\xab\x2d\xd3\x61\x94\x12\x61\xeb\x3c\x82\xdc\x10\xef\xb1\x9e\xdc\xac\xd6\x37\x6c\xa0\xd4\xb0\xfc\xe7\x79\x3c\x21\x32\x6b\x84\xc2\xfd\x4c\x90\x5f\xe5\xae\x29\x24\xde\x90\x88\x16\x3d\x2c\xad\x7e\x31\xf1\xba\x61\xb3\x19\x1f\x52\xb3\x89\x46\x4a\x9a\x29\x13\x00\x28\xf5\x9e\xf0\x8b\xb8\xd5\xd2\x8e\xb0\x0b\xd1\x6a\x5d\x36\x9b\xa8\xe3\x11\x12\xf5\x90\x6c\xb5\x80\x91\x0e\xf6\x11\x6b\xb5\x40\x67\x88\x20\x04\x1d\xec\xee\x3d\x7a\xd4\x8c\x70\xaf\x56\xce\xef\x94\xfe\xef\xef\x28\xec\x09\xbf\xdd\xc9\x22\xbc\xe0\xf5\xa6\x88\xb3\xc3\x42\x2d\xaa\x56\x21\xab\x94\xe2\x1e\x47\xd2\x4d\xd2\x20\x91\x4a\x31\xd9\xc1\xb8\x27\x5a\x3b\x7e\xbb\xe3\x73\x24\x2f\xc4\x25\xee\x39\x7f\x71\x6d\xae\xbd\x10\x97\xbd\xf6\x8e\x2f\x5a\x1d\xf5\xb5\xdd\x59\x60\xf8\x28\x36\xa5\x77\xa8\xd4\xa3\xa4\x9b\x05\x86\x9f\x62\x65\x86\x85\x2e\x2f\xb5\x30\x9e\x0b\x72\xb2\x9a\x56\xc1\xf8\xaf\xe5\xe1\xde\xa3\xf9\x7c\xff\x61\x99\x9c\x8d\x97\x52\x15\x86\x97\x62\x63\xe6\x0c\xaf\x5b\xf6\x4b\x57\x94\xc2\x69\x8d\xd8\xf6\xde\x23\xed\x9e\x3b\xf4\xe6\x73\x7e\x48\xd2\xcc\x12\xc7\x08\xff\x83\xb5\xd2\x45\x11\x93\x23\xcc\x38\xbc\x15\x1b\xd2\x46\x78\x2b\xdb\xc6\x56\xb5\x6d\xef\xd1\x3f\xd9\x7c\xce\xfe\xb9\xff\x10\x47\x03\x74\xb0\x6f\x7e\x3d\xf4\xb4\x7c\xc8\x0e\x1f\x3f\x9c\xcf\x3b\xde\xce\x21\xcb\xc8\x91\xa4\x73\xf0\x87\x6c\xb1\xf6\xa3\x87\xc6\xae\x57\xbc\xd8\xdf\xef\x56\x5f\xec\x3d\x2a\x89\xe6\x3a\xd4\xb0\xfb\xab\xc9\x9f\x5a\x39\x19\xf4\x84\xa6\x87\x5e\x2f\x5f\x01\x3e\x6d\xf1\xd2\xee\x1d\x66\xc6\x99\xb8\xb6\x0c\x5a\x2d\xdc\x55\x93\x3e\xee\x21\x46\x3a\x20\x4d\xa6\x98\xa5\x49\x1f\xe3\x66\x53\xc1\x2e\x8a\x69\x4e\xb3\x19\x6e\x32\xf3\x54\x7a\xd7\x8e\x36\xac\x31\x4a\x13\xd7\xc1\x09\x67\xb3\xc6\x97\xb7\x6f\x5e\x4a\x39\x39\x33\x62\x88\x1a\x39\x38\x1a\x20\x49\x28\x56\xda\xf2\xb2\x0f\x7a\x22\xe2\xa1\x60\x49\xe2\x54\x38\x4a\xde\xc6\xa7\xf1\x78\x92\x4a\x1a\x8c\x58\xb3\xf9\x4a\xad\x17\x8a\xee\x43\xea\x2b\x61\x80\xf6\x59\x1f\xc2\xc0\xe7\xae\x8c\x25\x1d\x99\xdd\x60\x45\x90\x81\xc3\x84\x88\x85\x53\x89\xf9\x43\x47\x1c\xdd\x0e\xd6\x96\x90\x46\x3c\x5a\x2e\x73\xb3\xbe\x8c\x22\xa8\x56\x60\x95\x9a\xb7\xe2\x58\x46\xf8\x48\x7b\xfd\x93\x49\xcc\x13\xf6\xf1\xec\x0d\x04\xef\xfd\xfb\x70\xe0\x73\x37\x91\x54\xa6\x09\x84\xaf\x8b\xe7\x73\x76\x2b\x17\x10\xde\xae\x38\x3e\x33\x8a\x4d\xf2\x93\x32\xc1\x5b\xb9\x14\x78\x96\x3e\xc6\xf9\x4b\xfc\xc5\x1d\x0c\xab\x33\xd9\x00\x85\xd0\x28\x25\x4a\x85\xcb\x27\xa1\xe3\x37\x1c\xdc\xf5\x0e\x63\x2d\xb7\x85\x19\xc7\x8a\xf8\x10\x79\x10\x2b\x09\xda\x7e\xb5\xd3\x8a\x31\x08\x72\x87\xce\x07\x76\xee\xef\x72\x8f\xb8\x95\xe8\x48\x69\xb5\x3d\xda\x72\x40\x67\x6c\xa0\x3e\xc5\x0b\x7d\x44\xb6\x08\x3d\x43\x5c\x6d\xaf\x47\xa3\xd1\x59\xd6\x2b\x2f\x19\xed\x33\x91\x20\x8c\x21\xb0\x7b\xcb\x1c\xe7\xd2\xbe\x49\xd3\x3f\x87\x3b\x9e\x37\x9f\xef\x7a\xde\x21\xc9\x5f\xe1\x82\x2d\x2a\xd1\x9c\x94\x85\x55\x5f\xc2\x11\x47\xb3\x81\xda\xa7\xbb\x82\x08\x24\x6b\x52\xc3\x8d\x89\xfd\xf3\xd1\xfa\xc2\x68\x32\x30\xb9\xca\xd4\xf6\x89\x38\xa4\x6e\x38\x71\xa9\x16\x29\xa5\xb8\xbb\xe7\x6e\x3c\x61\x1c\xa5\x6e\xf8\xa7\xfa\xf4\x08\xb6\xbc\xe5\xcc\x16\x7a\x6e\xdd\x0d\x14\xd4\x23\x85\x66\x6b\x7d\x26\x9c\xf0\xb6\x2b\xdd\xa0\x6b\x12\xd2\xe9\x20\x92\x6c\xa5\x99\x2e\x52\x2b\xc4\x24\x4e\x73\x03\xa5\x69\x17\xe4\xde\x4d\x34\xe3\x9b\xb8\x01\x70\x77\x16\xc9\xab\xa7\x82\xf5\x19\x97\x11\x1d\x25\x44\xb8\xfd\x40\xad\x52\xe1\x86\xbb\x58\x69\xcc\x6e\xb6\x02\x54\x91\x5d\x97\x9a\x86\xe5\xa9\x0b\x52\x37\x78\x54\x46\x61\x24\x8c\xf7\xd1\x87\x01\x62\xb8\x87\x56\xd0\xe3\x64\xea\x73\x5b\x51\xe0\x98\x83\xf4\xcc\x0d\xb0\xaf\x9f\x6c\x21\xc4\xa5\x41\x2c\x24\xc2\x8b\xba\xb4\x53\x0d\x35\xf5\x20\xf0\xa5\x1b\x00\xad\x2c\x01\x4e\x14\x6b\x28\x8d\x6f\x33\xf4\x7c\x50\xa4\xa7\xd7\x74\x7f\x13\x6b\x52\xe6\x38\x43\xa7\xcb\xdd\xf0\x6d\xb3\x89\x64\x8b\x38\x63\x47\xad\xef\x30\xcc\x7e\x46\x8e\x19\xc7\x72\xfa\x9e\xb1\xe1\xf3\xdb\x89\xa6\x6a\x79\x24\x6f\xa4\x92\xac\x7f\xac\x97\xf9\x79\x3a\x1a\x69\x85\x6f\x9c\x95\xdc\x9c\xad\x16\x32\x2f\xa2\xa7\x56\xa6\x09\x35\xc9\xd3\x03\x41\x4c\xda\x9d\x2e\x6d\xb5\x0e\x79\xb3\xa9\xc3\x61\xd9\x2d\x0b\x51\x88\x71\xb3\x19\x6f\xd9\x90\xdd\x12\x61\x54\x44\x70\xb5\x3b\x30\xc8\xc2\x55\x22\xb5\xbc\xa3\xdc\xce\x4f\xd8\x45\x74\xd9\x1d\x5c\xb4\xdb\xd1\x25\x09\x94\xe0\x1c\x68\xb1\x39\xcd\x33\x04\x5e\x07\xc0\x2e\xbc\x4b\x60\x86\x45\x00\x85\xcf\x3a\x23\x80\x09\x46\xc9\x2b\x2d\x56\x73\xf9\x8a\x48\xc8\x72\x17\x4a\x7b\x5b\x31\x89\xb8\x32\x0b\x92\x57\xa4\xd2\xcb\x15\xa0\x9a\xac\x19\x0d\x50\xd8\x6a\xfd\x93\xa4\x85\x14\x62\x19\x5e\xa8\x18\x6a\xe9\x3c\x0f\xe3\x68\xef\x42\x9e\x89\x5a\xa8\x46\x8a\x22\x7d\x54\x01\x79\x21\x2e\xbb\xf2\xa2\xdd\xd6\xe1\xac\xb7\x12\x31\xdd\xd8\x22\xcd\xbf\x6e\x2e\x87\x12\x7c\xa9\x8a\x9d\x4b\x08\xe1\x73\x21\xea\x63\x78\xb2\x59\x12\x92\xf9\x98\xda\x63\x59\x19\xd9\x2e\x2f\x78\x72\x98\x0f\x2b\xc3\x99\xff\xcc\x48\x20\x45\x00\xab\x39\x18\x44\x21\xe3\xd7\x18\x57\x11\x17\xd6\xfd\x1a\x3c\xc6\xb0\x72\x60\xde\xaf\xd5\x80\x79\x73\x53\xf6\xbb\x8d\xc9\xf5\xfe\xc7\x86\x92\xe2\xf0\x90\x2f\x70\xf7\x78\x6d\xbd\xe2\x9f\xff\xe4\x1b\x92\x28\xff\x53\x7f\xee\x56\x72\x37\xb2\x75\x47\x2d\x8b\xb3\x64\xaf\xb8\x64\x62\x4a\x47\xb6\x16\xf4\x8a\x23\xb6\xf1\x24\x59\x51\x48\xe0\xda\x59\xdf\x77\x56\x74\x7b\x63\x86\x9e\x4a\x70\xfe\xe2\x8d\x46\xa3\xe1\xc0\x0c\xbd\xd2\xbf\x1c\xe0\xb6\x3f\xe4\x4f\xbb\xc4\x1d\x3a\x95\x6b\x1b\xd8\x52\xe2\xbe\xa7\x38\x59\x51\xf8\x85\x5d\xf8\xf1\xc3\x43\x82\x38\x39\xd6\xc7\xb8\x9a\x4d\x7e\x48\x3a\x3b\x3b\x25\xec\x57\x0b\xb6\x00\x3b\x24\x8f\xbd\x66\xf3\x60\xff\x90\x58\xf6\x50\x2e\x57\x42\xee\x3f\x6c\x36\xf7\x1e\x55\x20\x85\x05\x69\x88\x99\xcf\xbf\x9a\x7f\x34\x12\xeb\x3a\x10\x59\xc9\x5c\x50\x5e\x91\x51\x79\xef\x52\xeb\x66\x8a\x35\x25\xa8\xf5\xde\x71\xb4\x4e\xa3\xd7\x87\x24\x6f\x20\x96\x64\x1b\x22\x49\x50\xc5\x52\x61\x1d\x64\x16\x6e\xa8\x53\x17\xf7\x21\x5d\x37\xcd\xee\x50\x2c\x81\xbb\xdb\x3d\xe9\xa7\x3a\x76\x9a\xaa\x11\xb6\x3f\xa6\xa0\xff\x31\x88\x8d\xfa\xb1\xe6\xcc\xa0\x89\xaa\x6d\xef\x68\x0f\xd9\x76\x35\xe1\xae\x92\xbc\x14\x19\x1c\x28\xb9\xd3\xe6\xf5\x00\xa4\x1b\xc2\x1d\x8a\x34\x66\x90\x2e\xd3\xe9\x96\x53\x10\x84\x82\x24\x4c\x9f\xff\x18\xac\x92\x1c\x1b\xba\xd0\x5a\x3d\x70\x86\x42\x09\x26\x79\xb1\x56\x3c\xe0\x58\xcd\x22\x08\x56\xa2\xe2\x84\xc3\x6f\xa0\xe3\x36\xa6\x44\x92\x0e\x8c\x24\xd9\x81\xbe\x24\x1e\x4c\xe5\x5a\xde\xb1\xc0\xb0\xbd\x52\xf6\x2d\xf2\x4b\xc0\x58\x6e\x3a\x6b\x5c\x64\x10\xc6\x70\xb5\x01\xd0\xb3\x01\x87\x1b\x00\x3b\x36\xe0\x64\x0d\x69\xd9\x69\x42\x98\xad\xf9\xbe\x93\x7d\xbf\x93\xe4\x27\xdc\xfe\x02\xc9\x8d\x24\xaa\xde\x05\x1c\x49\xc2\x39\x7c\x90\xe4\x0b\x3c\x97\x64\xc2\xe1\x7a\xf5\x80\xb4\x1c\x67\x01\x4f\xe5\x7a\x8b\xe4\x0b\xe0\xf0\xcc\xa4\xb0\x85\x57\x6b\xe1\x3e\xa3\x19\xfa\x13\x4c\x0e\x1a\x0c\xa7\x92\x6c\x9c\xb4\x5b\xb2\x9e\x21\x9a\xe9\x54\xbd\x66\xc2\xea\x2b\x04\xf2\x6c\xd1\xf6\x04\x85\xef\x92\xbc\x86\xf3\x5f\x20\xef\xe4\x59\xb9\x0b\x91\x3c\xab\x81\x43\x4a\x44\xbb\xa3\x6b\x08\xa5\x2e\xd7\xe5\x84\x81\x20\x29\x48\x42\x55\x05\x5f\xe4\xfa\x95\x7b\x6e\x56\xce\xb1\x6a\xe0\xd9\x06\xb8\xef\x0a\x6e\x86\xbe\x48\xf0\xe0\x4f\x81\x04\x6e\x77\xb0\x49\x23\x7e\x5c\x1d\x82\x3c\xb8\xd7\x52\xa9\x3d\x2b\x59\x78\x25\xb7\xa8\xe8\x09\xbf\xe3\xed\xec\xfd\x81\x44\x5b\x7f\xc0\xad\x4a\xc1\x0e\x6e\xeb\x44\x94\xad\x83\xfd\xfd\xdd\x83\x05\x9c\xac\x59\xc9\xa7\x12\x42\x99\x2d\xac\x37\x7f\x87\x1c\x6d\xda\xac\xd3\x74\x8a\xb8\x12\xd1\x78\xb6\xdf\x77\x30\xf6\xcd\xab\x16\xbf\xe8\x94\xef\x77\x30\xd6\xe2\x0e\x7c\x5e\xd7\x6d\xce\x5f\xfc\x2f\x8e\x9c\xd6\xb5\x44\xbc\xd5\xc1\x2d\xe4\xe0\x86\xd3\x7a\x27\xd0\x33\x99\x25\x49\x81\x67\x2b\x5b\x34\x43\xaf\x55\x77\x1f\xe3\x05\xbc\x5e\x46\xce\xfd\x6c\x5e\xac\xc8\x6e\x64\x1f\x81\xe2\x7a\xee\x2d\x59\x61\xdf\xe4\xb9\x3e\x3b\x26\x51\x44\x19\x56\x5b\xa4\x92\x00\x6e\xdd\x2e\x82\x5e\x08\xa4\x36\x00\x6a\x76\x2a\xa1\x76\xca\x19\x3a\x92\x20\xa4\xea\x70\xa4\xa4\x26\x25\x6b\xeb\xe9\x97\xf6\x1c\xd7\x69\x49\xdf\xb9\xf8\x87\xce\x84\xf6\x8f\x4b\xc7\xcc\x78\xaa\x26\x64\x71\x44\xa4\x51\x38\xe2\xf3\x68\x83\x00\x42\xe2\x5c\x98\xbe\x72\x29\x6e\x39\x97\x8e\x8d\x37\xdc\x84\x65\xc7\xcf\x4f\xe9\x50\x7d\x58\xc4\x0d\xf4\x92\x89\xdd\x20\x3f\x15\x16\x11\x24\xdc\xa0\xe7\x9c\x5f\xb1\xc6\xeb\x24\xe6\xee\x33\x16\xc6\x7d\xe6\xc6\x9c\x9d\x0e\x1a\x54\x36\xae\x93\x98\x3b\x2d\x23\x7e\x38\x70\xa2\xc7\xc7\x77\x96\x40\x1d\xdc\x72\x1a\x03\x1a\x8d\x74\xbe\xb7\x86\xbc\x62\x8d\x41\x3c\x1a\xc5\x33\x93\xad\xea\x5a\xa2\x3f\x05\x8a\xb1\x82\x9a\xd1\xbb\xc4\x77\xba\x35\xc1\x46\x09\x33\xba\x41\x11\xcc\xd0\x99\x84\xcf\x52\x47\xdf\x2c\x38\xa1\x84\x91\x58\x5f\xec\x92\x12\x61\x35\x31\x93\x42\x9d\x33\xca\x1b\x11\x97\x71\x83\xae\x68\x81\x4e\x9b\xc7\xe3\xc6\x24\x4e\x92\x28\x88\x46\x91\x8c\x58\xe2\xb4\x4c\xa3\xd7\xb7\x6f\xcb\x29\xdd\xbf\xa1\x1e\xf8\x58\x27\xb2\xcf\x06\x3e\x22\xba\xfc\x3b\x11\x07\x23\x36\x36\x95\xa8\x26\x6b\x27\xeb\x3a\xac\x2d\xc7\x57\xcd\xd4\x12\x9c\xbf\x5c\x76\x18\x4d\x19\x37\x18\x34\x9c\x83\x5b\xe8\x9d\x40\x33\xf4\x5c\xc2\x1e\xe8\xae\xcb\x5e\x87\x8a\x75\x7d\x94\x1b\x0e\x16\xdb\x9b\x16\x84\xbe\x84\xbe\x3e\x84\x0d\x3f\xf5\x61\xef\x97\x92\x7c\x82\xb7\x6b\x59\xda\x13\x24\xf0\x83\x27\x46\x89\xfc\x24\xc9\x4b\x89\x66\xe8\xad\x84\x1d\xd8\xdd\xc1\x18\xbe\x49\x72\x8b\x3e\x2a\x66\xf7\x49\xc2\x4f\xf5\x1f\x86\x1f\x92\x44\xf0\x64\xfd\x46\xad\x8f\x55\x43\xb4\x56\x18\x37\x75\xbd\x97\xe4\x06\xde\x49\xf2\x0d\xfe\x5c\xbd\x77\xe5\x99\x6a\xe1\xc5\xda\xaa\xf2\x4b\x1c\x7a\x3a\x31\x38\x7c\x95\xe4\x25\x70\x46\x12\x10\x6c\xb5\xa1\xba\x9b\x2b\xec\x33\xc4\x19\xec\xee\x00\x37\x76\xac\x00\xa4\x59\x5f\x59\x57\x4a\x97\x2e\xf2\xec\x7a\xac\xdc\xcd\x4e\x34\xcb\x30\xbb\x8a\x56\xd2\xe5\xaf\xea\x79\x29\x91\x78\xb0\xbb\x53\xf0\x99\xc2\xee\x5d\x12\xe0\xd2\x2e\x27\x33\x24\x98\xe6\x74\x39\x66\xb6\x8c\x59\x27\x24\x64\x39\xe6\xdd\x9d\x3f\x84\xcb\x80\x91\x77\xd9\x88\xed\xee\x80\x6c\x77\x30\x06\x4e\x78\x4f\xcd\x41\x77\x88\x7d\xe1\x0e\x41\x61\x97\x0a\xbb\x2a\xdd\x2d\xce\x86\x7f\x94\xf0\xa7\x82\x1a\xe0\x96\x84\x19\x7a\xa1\x43\xe7\xff\xf8\x24\xb1\x86\x2c\x33\xf6\xd9\x90\xd9\x2c\xd0\x9f\x31\xa4\x8c\x3c\x07\xca\x36\x78\x62\xb2\x4d\x5b\x1c\x7a\x65\xbb\x19\x83\xad\x0e\xdc\x0f\x7d\x06\xcc\x97\x0f\x76\x77\xe6\x1e\x0c\xfc\x34\x4f\x0d\x4c\x32\xc9\xea\x0e\xfd\xd0\x6d\xd2\x06\x98\xae\x12\x2d\x05\x11\x6d\xd5\x48\x22\x81\x99\xd1\xa2\xc0\x30\xa4\x24\xd5\x27\x96\x57\x76\x98\x77\xc8\x8b\x53\xa4\xff\xbe\xbb\x03\x8c\x68\xbc\x12\x78\x5b\x5a\xfe\xbd\x29\xa2\x4c\xd5\xd4\x96\xaa\x06\x0e\xc7\x50\x86\x7b\x7c\x93\x0b\x0c\x31\x5b\x31\x47\xb7\xb8\xbb\xbd\x80\x88\x91\x01\x87\x01\x23\x01\x87\x80\x6d\x16\xe0\x92\xea\xf7\x15\x1b\x57\x3e\xb3\x6b\x01\x5a\x9d\x5a\x60\xd6\x4e\xc1\xaf\xf2\xcb\xcd\x16\x0b\x18\x31\x92\x4a\xe8\x33\xb2\xf9\x9c\xff\x3d\xdd\xf7\x29\x04\x8a\x59\x50\xe9\x33\x08\x12\x5f\x42\x30\xf3\x39\x84\x67\xbe\xee\xcb\x29\x23\x82\xc3\x36\xdb\xbc\x2e\xc7\x8c\x7c\x85\x2b\xb6\x96\x0f\x1c\x76\x7a\xc2\xbf\x43\x63\x35\xf5\xb6\xcd\x29\x45\x35\x6b\x86\x8c\xa4\x1c\x26\x1b\xcb\x39\x8e\x29\xe8\x41\x76\x47\xcb\x8c\xad\x39\x3d\xe5\xe9\x30\x99\x8a\x54\x03\x8c\xec\xed\xea\xb3\x0a\x7b\xfb\x84\xc8\x5e\xc7\xf7\x20\x25\xac\x9b\x96\x91\x4d\xad\x56\x19\x7e\x5b\x4b\xfd\xae\x63\x22\x33\x2f\x55\x71\x98\xeb\x46\x76\x05\xe9\x78\x7f\x88\x16\xb5\xbc\x31\x29\x21\xac\x77\x23\xfd\x5b\x89\x4c\x4d\x6d\xe1\x0b\xbc\x80\xbb\x75\x4b\x42\xe1\x56\x95\xcc\xe7\x33\x34\x65\xe0\xfc\x5f\x0e\xa4\xd8\xaa\xc3\x50\x34\x43\x43\x06\x8e\xaf\xbe\x69\x6a\xb2\x6d\x9c\xea\x6d\xbc\x0a\x1c\x12\xaa\x8f\x7d\xce\x18\x9a\xa1\x2b\x06\x61\xab\xa3\x13\x01\x65\xdc\x86\x96\x9a\xe3\x8d\xec\x52\x52\xe4\xc6\xba\x95\x68\x80\xfa\x4c\x8b\xb2\x13\x66\x82\x89\x69\x7e\xb8\x65\xb1\x04\x94\xc2\x8d\x2c\xbe\x62\xb8\x65\x2b\x37\x23\xd3\x3a\x56\x6f\x50\x9a\x35\xe8\x81\x03\xc6\x00\x95\xaa\x06\xa5\x24\x2d\x53\x75\x4d\xd1\x9d\xa1\xe5\x4a\x4d\x54\x86\x35\x46\x4d\x59\x6a\x13\x94\x81\x29\x4c\x79\x9e\x0c\xb8\x61\x2b\xf4\x05\x43\x89\xac\x53\xc2\x32\x4a\x7a\x0e\x18\xc9\x8f\x99\x0c\xa6\xac\xa4\xe4\x16\xdd\xaa\x2a\x6e\xa5\xe9\x4f\xd6\xea\x80\xc4\x8a\x1e\x4d\x0d\xd3\xf6\xda\x2a\xa8\xe9\x19\x45\xca\xd1\x4a\x0e\x44\xa5\x95\x7a\x36\x23\x44\x66\x84\xfc\x5b\x9e\x5f\x57\x69\x4c\xf7\x92\xc8\x92\x90\x3b\x74\x63\x13\x22\x5b\x1d\x9d\x67\x4d\x93\x21\x6d\x4f\x47\x06\x78\x93\x5d\x77\xf7\x81\x11\xc9\xe1\x39\x5b\x2d\x4e\x7f\x60\xa0\x2f\xf0\xf2\x1f\x3c\x70\x80\xe3\xde\x0c\x1d\xa9\x45\xa6\xab\x78\x08\x1c\x63\xbf\x84\x49\x2a\x40\x1d\x03\xf4\x48\x03\x29\x69\xff\x7a\x79\x45\x76\xbb\xd8\x5b\xc0\x53\x46\x6e\x38\x7c\x25\x4f\x99\x5a\x8b\xaf\xd6\xce\x15\x56\xa6\x9e\x61\x7a\x12\x33\x73\xf8\x84\xe6\xef\xcd\xe4\x8e\x09\x35\xef\x63\x33\x58\xb1\x86\x8d\x2d\x58\x03\x61\xa5\x63\x49\x61\xa6\x03\xce\x66\x3a\x9e\x4b\xdf\xd2\xe0\x52\xd8\xf7\xbc\x43\xd9\xd3\x4a\x92\x22\xe3\x44\x2a\x01\xd5\xbf\x45\xaf\x98\xb1\x99\xb4\x3a\x5a\x04\x2d\x7b\x76\x19\x95\x58\xf3\x55\xd4\x5f\x57\x6f\x64\x38\x65\xeb\x1d\xed\x45\xfd\x9e\x99\x44\xdf\x2b\x93\xc8\xbe\x43\xe6\x0e\x9d\x32\x58\xab\xc8\x87\x12\xcc\xed\x62\x85\x69\x05\xc3\x39\x23\xcf\x39\x7c\x61\xeb\x42\x46\x66\xe8\x9c\xad\xf2\xaf\x3d\x65\x48\xe8\x98\x1b\x83\xe6\xac\x42\xbe\xd4\xa1\x67\xab\x51\x88\xdf\x41\x3d\xcb\x2e\xfd\xc5\x0b\xb5\x82\x4d\x15\xc7\x8c\x7c\xe6\x70\xb2\x76\x4f\x38\xe5\x48\x63\x3c\x66\xa6\x8d\xd8\xdc\x5f\xb0\xc1\xce\xf4\x65\x65\xf5\xde\x02\x90\x20\x33\xf4\x9d\xc1\x49\x86\x0a\x74\xbf\x9e\x31\x14\x4a\x0c\x4f\x19\x3a\xc6\x90\xe9\xa4\x72\x43\x05\x7a\x72\x2f\x30\x7c\xe6\xeb\x6d\x2b\x5f\x58\xb6\x7b\x75\xdf\x70\xf7\x9c\x26\x37\xe4\x3e\xf0\xbf\x42\xe8\xa7\x1c\xfa\xbe\xe4\xc0\xfc\xcf\x1c\x06\xc5\xa1\xe4\x32\xa2\x88\x59\xc2\x03\xfd\xd3\xdf\xea\x40\x10\xf9\x8e\x03\xc1\x75\x25\x8d\xea\xe7\x0a\x5c\xdf\x1f\xc7\x10\x7c\xa9\x40\x3c\xab\x40\x7c\xf0\x3f\x33\xe4\x38\x18\xe8\xc7\xfc\x69\xea\xdf\xd3\xc8\xbf\x91\x40\xaf\xd5\xdf\x70\xea\x73\xa0\xb1\x7e\xf1\x43\xff\xbd\xd3\x7f\x7f\xea\x25\x9f\x14\xe5\x3f\xe7\x4f\x41\xa8\xbe\x07\xa7\xf9\xef\xd7\xfe\x56\xc7\x4e\x0b\x68\xd5\x8f\x66\x68\x16\x6b\xe6\xad\x79\xca\x24\x86\x0e\x70\xec\x73\xdc\x72\x1e\xd0\x49\xf4\x60\xba\x63\xdd\x3b\xf8\x91\x6d\xcc\x2f\xfb\xb3\xfa\x79\xbf\xf6\xf9\x25\x5b\x65\x63\x2b\xd3\xd6\x55\x3f\xef\xd6\x3e\x7f\x62\x1b\x93\xd7\x7e\xab\x7e\xde\xab\x7d\xfe\xb1\xb9\xee\x27\x9b\xeb\x7e\xbf\x19\xf9\xbb\xcd\xed\xfe\x73\x33\xe5\x2f\x36\x77\xea\xd7\xcd\x94\xf3\x74\x63\x69\x91\x6e\xa4\x5c\xa6\x1b\x29\x67\xe9\xc6\x6e\x49\xab\x9f\x77\xea\x2d\xa3\x9b\x8b\x87\xa9\xed\x28\xd7\x1a\x86\x69\x1d\xac\xdc\x25\x5f\xc6\x4a\x43\x99\xa1\x77\x71\x66\xf3\x34\x16\x21\xeb\xca\xe5\x74\xf3\xad\xc6\x77\xe8\xad\x46\x61\x9c\xc7\x65\x02\xa3\xb4\x92\xc9\xf4\x5b\x5c\x77\x4a\x0e\xd1\xb6\xe6\x4a\x12\xe7\x06\xbb\x19\xb3\x1c\xd2\xc2\xdd\xee\x85\x29\xfa\xc7\x2b\x6e\x6e\xac\x88\xb8\x64\x43\x26\xfc\x86\xf3\x8f\x16\x6f\xfd\xc3\xf9\x07\xf6\xd3\x48\x07\x1b\xe4\xbb\x4f\x98\xa2\x2c\x8d\x38\xeb\x1b\xbb\x8c\xc4\x2d\xe4\x34\xfa\xd1\x30\x92\x09\xe8\xfc\xfc\xc3\x58\x9a\x4f\xba\x6e\xac\x33\x21\x46\x88\x47\x88\x6b\x77\x64\x99\x99\x24\xb5\x35\x1f\xeb\x6a\xe1\x14\xf1\xf2\x94\x2d\xd5\xc7\x2e\x02\x08\xc9\x96\x16\x75\xbb\x2b\x7a\xc9\x34\x6d\x8a\xc6\x11\xa4\xc0\x75\x34\x41\xf0\x1c\xb8\x4b\xcf\xb4\xcf\x44\x3b\x32\xa9\xbe\x49\xca\xdc\x16\x19\x16\xa7\xdf\x90\x84\x76\x47\x71\x8f\xca\x10\x51\x8c\x7d\xdd\xe5\x21\x78\x70\x4f\xcf\xb4\x15\xa4\xcc\x8b\x10\x28\xf5\xe6\xb9\xcf\xd4\x88\xbb\x74\x61\x8f\x48\x62\x4f\x8c\xab\x08\xcd\xd0\x76\x64\xd2\xcb\x3e\xd2\xf3\xc3\x6e\xff\xc8\x86\x55\x1d\x9b\x0f\x43\x9f\xde\xf9\xa6\x07\x2b\xee\xb9\xbe\xdd\x5f\x68\x86\x86\x11\xec\x01\xc7\xf3\xf9\x96\x7e\xee\x78\x1e\x70\x6d\x42\x54\x1f\xf4\x0f\xfb\x12\x69\xab\x30\x42\xbc\x4d\x3a\xf8\xc1\xde\xdc\xc3\x6d\xc4\x1f\x74\x3c\x6f\xee\xe1\x16\xe2\x0f\xf6\xf4\x93\x95\x57\xe7\x97\xf3\xf2\x4e\x35\xef\x7d\xac\x43\x5f\xcb\x54\x1b\x69\x05\xe6\x43\x54\x19\x90\xc0\xbe\x55\xfb\x2a\xad\x7a\x29\x23\x38\x8a\x2a\x7e\xc5\x61\xfa\x9b\x4e\xc9\x3b\xf4\x25\xd2\x99\xfe\xcd\x5d\x04\x0b\x0c\xa3\xb8\x82\x69\x62\x63\xe2\x3d\x47\x8a\x94\x39\xbe\x33\xa0\xa3\x84\x59\x3b\xc5\xac\x02\xe6\x6e\xcf\xe7\x8e\xb3\x95\x5d\x69\xad\x76\xad\xf2\x4c\xb8\x0d\xf8\x52\x8d\xf5\xab\x18\xde\x46\xf0\x41\x22\xde\x72\x88\x53\x99\xec\xb7\xe9\x5a\xf7\xa4\xf3\xdd\xc9\xae\x84\xad\xfa\x29\x6f\x2a\x84\x90\x72\x2a\x3d\x36\x53\xa9\xba\x30\x08\xaf\xc4\xae\xfc\x0b\x56\xc5\x7c\xee\x1d\x92\x3b\xf4\x22\x5e\x79\xe7\x80\xb4\x69\x5f\x80\xbe\x64\xe1\xbf\xbc\x90\xba\x45\xc8\x97\x95\xfa\xbd\x3a\x43\x9e\xa8\x4e\x70\xec\xfb\x7f\x3f\xa4\x1b\x37\xa9\xe7\x9b\xb7\x99\x6b\x7b\x61\x70\x77\xbb\xf7\x21\xf5\x9f\xa7\xd8\x5c\x0d\x51\x1e\x15\xdc\x5c\xc7\xab\xcd\x75\x9c\x56\x9b\xf0\x55\x35\xe1\x45\x64\x67\x72\xaf\x02\xe4\x03\x6d\xf0\x58\x70\xe7\x36\x5c\x90\xa2\xef\x69\x95\x45\x7c\xb1\xd7\xeb\x6d\x84\x3e\xa3\x8b\x19\x4a\x22\x48\x23\xf4\x34\x45\x1e\xc6\x70\x9e\xa2\xa3\x54\x3b\x49\x40\x7f\xc9\x3f\xbf\xd2\x2f\xe1\x34\x45\xcb\x83\xed\xfc\xf5\x97\x19\xe5\x75\x00\x5b\xde\x22\xc7\xf7\x1b\xa8\xcc\x21\xc5\xe2\x7a\x61\x7c\x69\xb7\xe0\xac\xb6\xfa\x32\x73\x48\x75\x34\x8e\xab\x40\x3a\x1e\x88\x67\x81\xf4\x65\xae\xf3\x1a\x50\xf9\xe5\x4d\x6a\x3b\xb0\x82\x2f\x65\xdc\x58\x78\xdc\x42\x33\x34\x1e\x80\xe3\xc0\x0c\xbd\x8c\x80\x49\x38\x4e\x15\x17\x1f\x80\x5e\xde\x27\x29\xbc\x57\x75\x9d\x62\x0c\x3f\x22\xb5\xb9\xe9\x6d\xb2\x25\xd4\x3f\x96\x20\x5d\xad\xe1\x56\xdb\x94\xce\xb5\xeb\xe8\x83\x4e\x13\x76\xa6\x17\xef\x4b\x9d\xb2\xfc\x3b\xf0\x65\x67\xd2\x74\x50\x10\x42\x71\x16\x4d\xb8\x5d\xde\x9c\xc6\xed\xc4\xe4\x5a\xfd\xd0\xe4\xbd\x49\xcd\xbf\xb7\x12\x3e\x45\xc8\x19\x44\x23\xc9\x84\x62\x44\x99\x43\x29\x24\x33\xf4\x33\x5a\x2d\xa4\xdc\xa5\x39\xf7\xc4\x0b\x38\x43\x1c\x3e\xa3\x8b\x53\xe4\x24\xd1\x88\xf1\x90\xf5\x1d\xb8\x95\x68\x92\x1a\xaa\xb6\xb4\x15\x43\x0d\x32\x72\x22\x7e\x15\x05\x91\x5c\x86\x60\x39\x04\x0d\xa5\x4e\xd7\x64\x7f\xf6\x20\xcd\x3f\x0b\x16\xb2\x68\xca\x84\x03\xb3\x6c\xe6\x20\x67\x28\xe2\x74\xe2\x40\xa8\x26\x47\xb1\xe5\x7b\x87\x7f\x0a\x14\xe2\x9e\xd3\xcb\x7d\x23\x4d\x05\xe2\x3b\x16\xf7\x7e\x96\x66\xa2\x4f\xdb\x1c\x8b\xdb\x9e\xcf\xb3\xa7\xbe\xf5\xcc\xca\xbe\xe4\xdd\x12\x98\x19\x20\xf3\x40\xcb\x01\xec\xeb\xf1\x63\x90\xbb\x9d\xa5\x4e\x39\x2f\x75\xca\x79\xe9\xb2\xd2\xea\xf4\x2a\x52\x3a\x88\x66\xb5\x21\xe8\x9f\xe6\xd8\xb2\x8e\xf5\xd0\x49\x60\x18\xce\xdf\xe7\x89\x49\x8b\x34\xd8\xba\xa2\x28\xab\x28\xd2\x15\x45\x6e\x08\x92\x20\x4a\x22\xb7\x8f\x55\x79\x42\x5d\x06\x21\x89\x6a\x95\x7a\x40\xdd\x00\x68\x5e\xe9\x12\x0d\xb1\x1b\x40\xec\x86\x10\xbb\x7d\x88\x15\x0d\x12\xe7\x90\x8a\x0c\xa1\xc9\x28\x95\xac\xff\x4a\x1f\xf6\xf3\x3e\xec\x2f\xf7\xa1\xea\x02\xa6\x1b\x98\xea\x5b\x76\x29\x61\x6e\x08\x21\x61\x8a\x2c\xc2\x96\x7a\x32\xd2\x1b\xdc\x80\xac\xe8\x4d\xa9\x37\xae\xb2\x37\xf3\xc4\x01\xa6\x37\xed\x82\x8c\x20\x7d\x85\x16\xd6\xd5\x22\xb5\x72\x18\xd6\x95\x73\x5d\x39\xd7\x95\xf3\xa5\x1e\xcd\x83\x60\x32\x5a\x90\x50\x03\x8e\x57\x0e\x66\x07\x22\x18\x00\x5b\xa2\xc5\xea\xd3\x8f\x4b\x62\xcc\xa7\x01\x4c\xab\x02\xca\xcf\x2a\xcc\x34\x28\x9c\xef\xa5\x22\x5a\x13\x97\x02\xb8\x0f\x43\xa5\xcf\x87\x6f\x95\xa2\x5c\x81\x7d\x5b\x85\x7d\xae\x05\x80\xb1\x6a\x88\xfe\x57\x49\x14\xe3\x01\xbc\x0a\xe0\x65\x8a\x9c\x8b\xf6\xc5\x5f\x7f\x5d\xde\x2f\x10\xfe\xa3\xd5\x73\xe1\xaf\xbf\xfe\xfa\xeb\x7f\x6c\xcf\xff\xed\xaf\xbf\x92\x4b\x07\x6b\x9b\x46\xa0\x0d\xaa\xaf\xe2\xd5\x87\x6c\xc2\x57\x0b\x25\xf8\x28\xfe\x8e\x8d\xc1\xa3\xae\xe3\x7c\xaa\x33\x6d\xe7\x3e\x5f\xc6\xa0\x63\xd2\xbe\x33\xc5\xbf\x38\xc6\x2d\x67\xe1\x54\x16\xf5\xb7\xcd\xda\xd8\x8f\xda\xe6\x5c\xdf\x9d\x9f\xd4\x94\xbd\xfa\xf6\xfc\xbe\xfa\xfd\x71\x5d\x47\xae\x7e\x7e\x54\xd7\x91\x7f\x5f\x40\xbd\xe3\x55\x01\xf5\xbe\x3a\x60\x2f\x6c\x4c\x7f\xa6\xc8\x30\x60\x4e\xc7\xcc\x81\xb3\x00\xa9\x51\x33\xdc\xd1\xa4\x6b\xca\xde\x7d\xc9\xd8\x70\x72\xc6\x86\xec\xd6\x81\xf7\x6a\xab\x08\x86\xf9\xdb\xe7\x3f\x52\x3a\x52\xdd\x3b\x1e\xc0\xeb\xc0\xec\x6a\xef\x07\x8a\x86\x01\xae\xed\xbd\x5f\xd3\xd5\x61\x6e\x9c\x96\xbb\xd9\x0c\x7d\x54\x13\xa1\xb3\xb7\xe7\xe1\xd6\xc3\xce\xe3\xbd\x83\x47\x8a\x43\x89\x43\xaf\x27\xda\x9d\xbd\x03\xef\xf1\x81\x2f\xf0\x03\xfd\xf4\x70\xee\xa9\x55\x6a\x5e\x3f\xfc\x43\xaa\xe5\xc7\xda\x88\xe9\xaf\x5a\xe3\x60\x0f\x76\x0f\xf6\x77\x8c\x1e\x62\x5e\x3f\x3e\x98\x7b\x18\xab\xd7\xf3\x3c\xea\xf6\x9e\x7e\xf2\x11\x27\xac\x8d\x76\x0f\xf6\xff\x48\x5b\x28\xcd\x34\x97\x34\xd3\x5c\x30\x6e\x23\xd4\xd9\xdf\xfd\x03\x09\x82\xf6\xff\xe0\xad\x1d\xfc\xa0\xb3\xbf\xab\x6a\xd8\xc1\x0f\xf6\xd5\xbf\x1d\xa0\xb1\xcf\x88\x68\x21\x71\xd8\xf1\x7a\xbb\x7e\xfb\x31\x86\xa0\xe3\xa7\xad\x3d\xcf\xfb\x43\xb6\xd0\xce\x21\xeb\x79\x7e\xc7\xd6\x62\x04\xad\xac\x9f\x17\x01\xec\xc1\x0c\xf1\x04\x44\xa2\x67\x29\x72\xda\x6a\x02\xbf\x08\x60\x07\x56\x39\xe1\xea\x2e\xb8\x4e\xcd\x05\xb7\x53\x73\xc1\xed\xd6\x32\x2e\xec\xd5\xf2\x33\xec\xd7\x8e\x99\x1f\x54\x6f\x4c\x6c\x3c\xac\xdd\x56\xf8\xa8\x76\xc0\xff\x71\xed\x7a\xad\x8e\x57\xbf\x2e\xab\xd3\xa9\x7b\x01\x3b\x3b\x8b\x05\x9a\xa1\x27\x41\xd6\xe8\x6a\xab\x67\xe8\x6d\x50\xf6\xc6\xb9\xf5\xfe\x93\xf5\xde\xb7\xde\xff\x58\xf3\xfe\xab\xf5\xde\xcd\xde\xef\xc2\x0c\x7d\x2b\x2a\xd6\xff\x6b\x39\xdf\x2c\xb6\x20\x69\x45\xca\x1a\x9a\xdc\xa4\x86\xdd\x07\x03\xac\xb6\xa1\xd2\x01\x72\x1f\x1e\xfb\x9a\xef\x9d\xfa\x5b\xa2\xd9\xd4\xf7\xa1\xcf\xe7\xb2\xa7\x9f\x77\xfc\x5d\xbf\xa3\x6d\x9d\x6e\xf0\xc5\xb6\x22\xd9\x53\x80\x1f\x7a\x99\x34\x1a\x24\x68\xe5\x42\xaf\x07\x09\x71\xad\x61\x09\x2b\xe6\xa7\x71\x8a\xc4\x03\x36\xf7\x7a\xbc\x85\xae\xa5\x79\xc6\x2d\x24\x5b\x4e\xc3\xc1\xd8\x57\x1c\x76\x18\x19\xc7\xc0\x42\x2f\x60\x07\x58\xa4\x64\x7c\x48\x12\xac\x4f\x70\x94\x26\x2c\x8b\xb6\xad\xc2\x1a\xd0\x6c\x6e\xd9\xe6\x80\xdc\x38\x60\xec\x01\x96\x7d\xcb\x6e\x98\x5a\x56\xc6\x24\xa0\xa4\xdf\x69\x02\x1c\xf6\x70\x3b\x7b\xea\x78\x1e\x6e\xe5\x6f\x3d\xcf\xa6\x20\xa4\xff\x7f\x9c\xee\xa5\x51\xce\x6e\x9e\x8e\x67\xe8\xa8\x99\x78\x5f\x6d\x96\x57\x6b\x56\xa7\xd6\xac\x9d\x5a\xb3\x76\x6b\xcd\xda\xab\x35\x6b\xbf\xd6\xac\x83\x5a\xb3\x1e\xd6\x9a\xf5\xa8\xde\xaa\xc7\xf5\xeb\xed\x3a\xde\x52\x33\x6d\x93\x7a\x64\xad\x22\xa4\x3d\x9a\x7a\xd8\x35\xcf\xd6\x37\x3c\x71\xb5\xa2\xf4\x6b\x25\xb3\x69\x86\xad\xdf\xcb\x02\x5c\x89\x4a\x9d\xbd\x83\x8e\x7e\xcd\x2a\xb0\x85\xf0\xae\xf8\xac\x68\x75\x3c\xef\x0f\xde\xda\xfb\x43\xb6\x98\x4b\x5b\x88\xb9\x41\xaf\xe3\xdb\x16\xa7\x81\x4d\x8d\x20\x8a\x38\x22\x08\xc7\x70\x4f\x13\x9f\xb7\x29\x45\x42\x33\x6e\x61\x07\x42\x5f\x25\x4a\x2e\xec\x68\xf1\x90\x26\x16\xb6\xc0\x9e\xe6\x8f\x0e\xf6\x98\x9e\xe8\x0f\x3b\x8f\x3b\x07\xf6\xdd\x32\x09\xad\x6e\xe1\x09\x74\x76\x0d\xdf\xb1\xac\x75\xb4\x1e\xeb\xdd\xdb\x96\xc8\xf9\x70\x15\xa7\xa3\xbe\xbe\xf5\x37\x60\x0d\x36\x9e\xc8\x3b\x07\xfb\x33\x74\x9c\xc0\x54\x22\xe7\xb3\x88\xf9\xb0\xf1\xea\xc3\xe9\xa3\x03\xaf\xd3\x18\xc4\x62\x4c\xa5\x83\xe1\xaa\xa6\xb7\xf7\x6d\x02\xce\xd1\x5d\x0c\xf7\x67\x8a\xd1\x6c\x79\x18\x3e\xe4\x0f\xe7\xf9\xc3\x4b\xf5\xf0\x49\x69\x52\xdf\x19\x48\xaa\xd9\xa3\x6d\x25\x98\xda\xd8\xa8\x66\x57\x1c\xe3\x0d\xe4\x4e\xaa\x86\xa7\xed\x0a\x5f\x0d\x4d\xe2\x90\x53\xc3\xd3\xbe\x54\x23\x1f\xb3\xd5\x21\xeb\x8b\xff\x14\x6d\x75\x60\xcb\xab\x67\xfb\x34\xaf\x3b\xf5\xac\x40\xa7\x68\xcb\xd3\xd0\xb5\x79\x6a\xde\xab\x4d\x19\x61\x9d\x66\xb1\x60\xe6\xc1\x40\xf5\x41\xea\x06\x18\x82\xa1\xcf\x21\x18\xfb\x42\xf1\x6f\x66\x5b\x21\xab\xdb\xc3\x75\x37\x1f\x3c\xad\xa7\x04\x91\xee\x90\x77\x23\xa6\x48\x09\xe3\xf1\x64\xc4\x24\x6b\xd0\x7e\x3f\xe2\x43\x1d\x51\xa7\x0f\x43\x29\xf5\xd9\x17\x6e\xd0\x9b\x48\xd3\xdf\xdb\xfa\x2a\x51\x5f\x95\x7d\x6b\x00\x92\x06\x15\x4c\x27\xbe\x88\x04\xeb\xdb\x96\xa9\xab\xea\xbc\x7a\x97\xc0\x8e\x9a\x56\xb7\xe8\x47\x02\x9d\x0e\x74\xd4\x0f\x3d\xdd\x76\xf2\x5d\xce\xb2\x7b\x2e\xcf\xc9\x4e\x7d\x4e\x4e\xe8\x46\x07\xcb\xac\xda\x01\xa1\x49\x00\xf3\xd1\x0c\xe4\xa9\xb6\x43\xd0\xcf\x5a\x0f\x4a\xb4\x1e\x34\xed\x96\x8e\xbd\x19\xda\x1e\xc1\x54\xc9\xaa\xf4\x83\xf6\xef\xe5\x2f\x94\xe6\xe8\x87\x90\x98\x17\xa3\x11\x50\xed\xbe\xd3\xbf\x5e\x26\x6a\x45\x7f\xc1\x90\x6a\x47\x9e\x80\xe0\x34\x03\xd3\x81\x55\x35\x5f\xde\x9d\xdd\x42\xa5\x3c\x22\x4e\xf4\x98\x61\x77\xbb\x37\x1d\xf9\xaa\x75\x15\xb3\xcf\x2d\xdd\xe8\x11\xba\xd9\xdc\x1b\x47\x76\x75\xdb\x03\x74\x3b\xaa\xae\xc1\x0f\x9b\x8b\x3f\xa7\x9b\xcd\x88\x9b\x3f\x3f\xad\x08\x12\xd5\x7c\x39\x96\x19\xb1\xca\xfc\xb4\xcc\x7e\x6c\x44\xf6\x19\x7a\x39\xd2\x31\x13\xa5\xca\xf6\xd7\x5f\x3d\x63\xda\x71\xe9\x3e\xc6\xd8\x0d\x7a\xa7\x3a\xb3\xbb\x70\x03\x63\x12\xcb\xe3\x47\x85\x1b\xe8\x18\x0b\xec\x9f\x22\xe7\x81\x03\x37\xc5\x71\x22\x5d\xc9\x9b\x11\xfc\x1c\xc1\x39\xe2\x70\x4f\xf7\xb5\x77\x56\xfa\x0a\x4f\x78\xa6\x26\xfe\x02\xeb\xf1\x78\x1e\xab\x77\x96\x49\xd3\x22\x55\x93\xdd\x5d\x4a\x84\x96\x6f\x79\xb9\x4a\xa6\xca\x57\x37\xbf\x4c\x9b\x2a\x3f\xec\xf8\x15\x2d\xac\xfc\xb0\xeb\xdb\xf7\xf9\xdb\x5f\xbc\xf2\xcb\x41\xe5\x43\xb1\xa3\x7e\x1b\xd5\xb6\xd0\x4f\xa3\xda\x1e\xfb\x63\x54\xe7\x3c\x6f\x47\xd6\xe0\x7d\xa7\x1b\x5d\x8d\xe7\xd5\xcf\x9d\xfa\xd8\x7f\xa9\x7e\x7f\x58\xfb\x7c\x56\xfd\x7c\x50\xfb\x7c\x6c\x75\xf4\x1b\x69\x39\xef\x3a\xd9\x35\x24\xdc\x57\x6a\x8f\x16\x35\xb1\xab\x14\xbc\x27\x11\x50\x9d\x80\x19\x57\xef\xf8\x3d\xa9\xea\x33\xbc\x0f\x9f\xd1\xc5\x8b\x11\x72\xe8\x88\x09\xd9\xd0\x7f\xdb\x33\x2a\x78\xc4\x87\x0e\xbe\xc4\xea\xb3\xec\x23\x4d\x40\x55\x51\x7c\x53\x99\xcd\x29\x12\x6a\x2f\x8a\xfa\x3a\x0c\x53\x8b\xd9\x14\x4e\x7d\x2f\x93\xa7\x17\x15\xb6\xf6\xb9\x4a\x44\xd2\x87\xfc\x9e\x88\x80\x55\xd7\xe3\xb3\x2a\xe4\x9f\x23\x70\xae\x04\x1b\x38\xf0\xe0\x7f\x5c\xd3\x29\x35\xf7\xb5\xf8\x0f\x22\x57\xb2\x44\x22\xc4\x09\xc7\xc5\xe9\xcc\x07\x7f\x25\x0f\x86\xe0\x38\x18\xeb\x24\xc1\xb6\x6d\xab\x8a\xf5\x3b\xab\xbb\x4c\x2d\x33\xab\x34\xbd\x58\x37\xb6\x8e\x75\xc7\x69\xf2\x60\xd6\x47\xce\xf7\x60\x44\xf9\x8d\xd5\x63\x5c\xf7\x16\x9c\xe8\x6b\x9f\xfb\x30\xd1\xc9\xd7\x8e\xab\xe6\xa0\x0a\x6b\x56\x32\x16\xb7\x43\x8e\x6e\xfa\x70\x0c\xda\x78\x7f\x5b\x8c\x92\x64\xb7\xb2\xcd\xe3\x99\xa0\x13\xab\x2e\xd1\x72\x7c\xf5\x13\xc3\x0c\xdd\x15\xb0\xb3\x76\xc7\xf3\x34\xd4\xeb\xe5\xd1\xfb\x49\x37\x85\x70\xcd\xe7\x2b\x23\xb6\xc6\x05\xee\x40\xf2\x46\x20\x79\x3b\x4e\xe5\x28\xe2\xac\x1d\xf1\x41\xdc\x08\x62\xd1\x67\xa2\xed\x39\x18\x74\xc7\x18\xfa\x66\x68\x50\x14\x1b\xd0\xc6\x80\xb6\x75\x89\xf0\x8a\x0a\xd9\x18\x8b\xf6\x8e\x26\xf1\x18\x83\xec\x23\xe7\x43\x9c\x8a\x90\xe9\xb6\xf8\xea\xb7\xbd\x91\xbe\xdc\xdc\x5d\xdc\x26\xae\xad\x6d\xc7\x1a\x7d\x63\x1c\x64\x75\x68\x62\xc4\x52\x1b\x92\x71\x4e\xb9\x88\x86\x57\xb2\xed\x35\x74\x2f\x8f\x53\xa9\x36\x72\x98\xa1\x51\x1f\x9c\x34\x61\xa2\x9d\xb0\x11\x0b\xa5\x03\x4e\xc4\x23\x19\xd1\x51\xf1\xb5\x3d\x8e\x7f\xb6\x7f\x01\x32\x63\xc1\x4d\x24\x7f\x01\x95\x11\x12\xc6\xa3\x58\x38\xe0\xfc\x5b\x18\x86\x95\x71\xfe\x07\x29\xbc\xf2\x66\xb8\xe3\x95\xcd\x19\xb6\x07\xb4\xcf\xfa\x95\x21\x4a\x58\x18\xf3\x3e\x15\x77\x0e\x86\xcf\x14\xbd\xa1\xe8\x54\xc7\x6d\x61\x0c\xd3\x3e\x72\x8e\xb5\x9b\xa0\x11\xdc\x35\xe4\x55\x94\x34\x46\x34\x60\x23\xab\x6a\xa7\xa5\x07\xa5\x32\x87\xde\xda\xd2\xf0\xbf\x3d\xc8\x9c\x04\xc9\x03\xce\x66\x3d\xe3\x75\x20\x4e\xeb\x6d\x84\x3e\xd5\x04\xdd\x4f\xd6\x40\x1e\xa7\x88\xbb\xc1\x7b\x37\x78\x5b\x09\x48\xf8\x9b\x73\xed\x2d\x45\x4b\xcb\xb8\x90\x9a\xbe\x19\x8f\xb0\x97\x79\x35\x06\x52\xd5\x78\x85\xb5\xe1\x6b\xf5\x04\x0d\xd8\x68\xd4\x4e\x46\x34\xb9\x6a\xc7\xcb\x53\xd4\x34\xd3\xcc\x51\x73\x76\x07\x36\x91\xdb\xa7\x7c\xa8\x3a\xb6\x42\xb0\xdd\x5d\x4e\x4b\xfc\x06\x25\xeb\xe8\xe8\x6b\x42\xac\xde\xfd\x56\x5d\xd9\xd7\xfd\xda\x19\xdd\x1f\xd5\xef\xc2\xda\x01\xa2\x21\x57\x53\x73\xd0\x0e\x19\x57\x93\xa1\xa8\xd2\xcc\x81\x57\x8a\x15\x06\xa7\xb5\x59\xf0\x64\x05\x33\xbf\x52\x6d\x76\x40\xdf\x6e\xc5\xe1\x4d\xdf\x86\x7f\xbf\x59\xc4\x7a\x47\x37\x9a\x79\xff\x5c\xad\x96\x70\xdb\x87\x97\x29\x06\x5b\x72\x3e\xd7\x27\x5d\xb5\x7a\xb0\x63\x12\xcd\xeb\x1b\x91\x0a\x4d\xa1\x12\xc7\x64\xb7\x63\xd5\x84\xaa\xd8\x98\xb8\x1b\x0c\x32\x53\x93\xac\xda\x98\xf2\x19\x17\x8c\x61\x9d\x8d\x49\x1b\x6c\x17\xd5\xd8\x8c\xaf\x76\xf5\xa7\x88\xeb\x74\x1c\xa5\xf5\x35\xac\xfa\xbf\xfb\x8a\x75\x4c\x52\x99\xf5\xf1\x57\x9a\xf7\xf5\xfb\x7e\x65\x32\x88\x70\x69\x70\x6e\xd8\x5d\x3f\x9e\xf1\x62\x74\xde\x55\x46\x47\xae\x2c\x90\x4e\xd6\x80\xb3\x70\x8d\x38\x11\xc6\xa3\x46\x18\x8f\xda\x34\x95\x71\xc9\x7c\x7f\x93\x47\xc7\x1b\xd7\xbe\xe1\x5f\x33\xf4\xb1\x0f\x5b\x3a\xc0\xa5\x98\xa0\xda\xa7\xbb\x96\x31\x56\x17\xa4\x8d\xa5\x53\xc1\xe2\xfc\x3f\xff\x77\xce\xeb\x2a\x13\x3d\x0d\x37\x8a\x70\x34\xdc\x28\x20\x86\xcb\x1d\x3b\x8e\xd3\x84\xe9\x95\xb6\x2c\xf8\xc4\x6b\xc0\x47\x8c\x4e\xd9\x32\x78\x14\x6e\x94\x1f\x07\xe1\x46\xa5\x29\x08\x37\xae\xb9\x24\xdc\xb8\x62\x47\xcb\xa4\x06\xa3\x74\x45\x9b\xfa\xff\x1b\x27\x4b\x3a\xad\x4f\x16\xfe\x37\x27\x8a\xc2\xf0\x7b\x13\x65\xba\xb9\x3b\xb7\x37\x4f\x94\xf1\xe6\xb1\xba\x0a\x37\x06\xa1\x0c\x37\x4f\x84\xc9\x66\xe4\xb3\x70\xa3\x02\x7b\x17\x6e\x56\x72\x6e\xc3\xff\xb5\xb6\xe0\x9a\xbe\xf6\xd0\xb6\x03\x84\x75\xcb\xc9\x4e\xdd\x70\x72\xb4\x6e\x3a\xf6\xa9\x64\x15\x19\xb0\x26\xd4\x97\xd6\x82\xb0\xd8\x17\xf4\x51\xbf\xf1\x00\xe2\x08\x79\x5a\x1b\x8f\xf1\x2a\xd1\x34\xa4\x23\xa6\x84\xb0\xef\x8d\x71\xcc\xe5\x55\x8e\x1a\x09\x22\xc1\x86\x13\xf1\xcc\x40\xb4\xaf\x74\xb6\xa2\x55\xab\x62\x22\xd8\xb4\xad\x81\x1a\xfd\xf6\x60\xc4\x6e\xb3\x6d\xdb\x4c\xd8\x67\xd3\xa2\xc8\xc7\x69\xb1\xc5\x0b\x11\xcf\x9c\xb5\xd2\x06\xe5\xc3\x11\x6b\x8f\xd8\x40\xaa\x5f\xbb\xb7\x8d\x30\x15\x49\x2c\xda\x93\x38\x32\x88\xb5\xf4\x71\x99\xb3\xd8\x92\x14\x43\xaa\xea\xb2\x3a\x29\x45\xd7\x5d\x2b\x45\xc8\xf8\xcd\xb2\xc0\xa3\xd7\x53\x38\xce\x84\x99\xdf\xf0\x9c\x39\xaf\x29\x4f\x95\xf4\x5a\x9d\x45\xce\x31\x0b\x84\xf5\x3e\x9f\x4d\xce\x5b\x2a\xc2\x2b\xa7\x3a\xa5\x9c\xa3\x89\x88\x46\x4e\x75\x5e\x39\x6f\x69\x5e\x78\xbf\xa8\x2b\xe5\xcc\xa9\x5a\x10\x9c\xd7\xe9\x28\x87\x7b\x58\xe0\x4b\x87\x69\x22\x9d\xaa\x69\xc1\xf9\xc0\x26\x92\x8d\x03\x26\x9c\xaa\x99\xde\x39\x0d\x65\x5c\xbe\x2e\xac\xf5\xce\x49\x3c\xcd\xe0\xab\x33\xda\x79\xc6\x42\xf3\xc1\x72\xc0\x09\xbc\xdc\xff\x5c\x4f\xd6\x75\x53\xe1\xf3\x7f\x7a\x2a\x68\x85\xe8\xd7\x73\xe1\xd2\x0c\xe8\x9b\xa9\xce\xc2\x51\x59\x22\xcf\xab\x8b\x2c\x16\xe0\x8c\xe9\xad\x39\x30\xe7\x40\x3d\xba\xf5\x3a\xac\x58\xc8\x5e\xf7\x74\x23\x8f\xeb\x33\x7f\x1c\xf7\xe9\xa8\xa1\x54\x9c\x46\x72\xa5\x5a\x91\x69\x4f\xfd\x28\x99\x8c\xe8\x9d\xa3\x36\xa0\x38\xbc\x59\xb5\x68\x74\xd1\x76\x3f\xa2\xa3\x78\xd8\xb0\x7f\x64\x3d\x56\x2e\xf7\xe5\x52\xa1\x49\x18\xb6\x1e\xa0\xbe\x56\xcb\xad\x25\x1c\xc5\x09\x6b\x8c\xf3\x2d\x4e\xef\x28\x21\xfa\x30\xb5\x77\x93\x5b\x67\xf5\xd2\x52\x98\x4d\xee\xe6\x1c\x6f\xda\x87\xbb\x10\x74\x14\xcb\xb4\x02\xac\x55\xfe\x86\xa2\x93\x46\xbc\xa4\x44\xf3\xa9\x0a\xe0\x44\xb6\xf7\x1a\x8a\xc9\x5c\xa7\x89\x8c\x06\x77\x79\xdb\x6a\xeb\x76\x86\xbe\xa9\x31\xf5\x54\x61\xfd\xd4\xc9\x87\x7b\x0d\x9d\x83\x38\x96\xab\x7b\x60\x3c\x6a\xef\x34\xea\x3b\x6c\x92\x86\x21\x4b\x12\xb5\xad\x6f\xe8\x98\xa7\x94\x87\x46\x19\xad\xee\xd7\x15\x94\x13\x11\x8d\x0b\xe5\x76\x16\xa2\xe7\x15\x14\x1f\x98\x6c\x3c\xa3\x92\x3d\x38\x8f\xc6\xcc\xda\xb4\xd7\x77\x38\x0d\x6f\xfa\x22\x9e\xd8\xb3\x2c\x9f\xf1\x7e\x0e\x6e\x66\x5d\x38\x8a\x26\x0e\x38\x82\x85\x12\x79\xfa\x92\x0a\x0f\x17\x53\x72\x12\x27\x91\xbe\xc0\x12\x9c\x41\x74\xbb\x61\x76\xe9\x8a\x72\xfd\xee\x17\xf4\x94\xa4\x58\xc6\xe5\xcd\x3b\xfb\xab\xcd\x32\xdc\xe9\x66\xa9\xe2\xfb\x66\xb9\xe0\x7c\x79\x91\x8b\x78\x96\x2c\xaf\xef\x2f\x9b\xf1\x9c\x85\x76\x8c\xc9\x53\xa9\xcf\xf5\x7c\x46\x17\x96\xb6\xec\x80\x76\x62\x38\xac\x1f\x49\x47\x0d\x9d\xb6\x90\xff\x1d\x5b\x81\xb0\xa6\xc5\x73\x85\x45\xf5\x63\x19\xfd\x19\xbc\x77\x83\x77\x3d\xe1\xff\x4d\xac\x33\x34\xdc\x56\xa4\x5d\x1b\x67\x89\x55\xc7\x19\x33\x37\x23\x38\xd5\xf1\x3a\xb6\xda\xaa\x03\x16\x44\x19\xb0\x20\x6c\x4b\xe3\x53\x09\x5b\x4a\xe9\x6c\x36\x45\xcf\x21\x8e\xaf\x9e\xe7\x73\xd1\x2b\xdf\xfd\x87\xe3\x3b\x5b\xfa\x0f\xd1\xdd\x65\x22\xbb\xdc\xe0\x4b\xa5\xc2\x93\xcd\x15\x82\x20\x6f\x19\xba\xa5\x35\x23\xae\x89\x95\xc8\xeb\xf2\x96\x6a\xaf\x06\x4d\x58\x71\x9a\x33\xf4\x63\x0a\xb7\x3a\xf1\xb1\x6e\xaa\x6d\x39\x0e\x33\x33\x6b\x35\x47\x4a\xe3\xff\x9c\x65\x55\x26\x6b\x71\x83\xd8\x78\xcc\xdc\xe0\x91\xf6\x99\x51\x97\xee\x6a\x73\x03\x75\xc3\xbd\x8a\x88\xf7\xff\xd9\x6d\x6a\xb2\x5d\xfd\xae\x33\xfd\x3b\x9b\x34\x25\xbd\x9d\x19\x56\x2b\x56\xea\x43\xbf\xd8\xc2\xe4\xef\xec\x1e\xec\xbf\xc0\xa2\x2d\x5f\xc3\x66\x6d\xeb\xd9\x2a\x95\xa5\x10\x2e\xb3\xa0\xe5\x9a\x68\x39\x61\xbc\x1f\xf1\xe1\x92\xb4\xc6\x6e\x27\xda\xf9\x6b\x1f\x55\xac\x72\xc6\x0f\x2b\x66\x49\x39\x0e\xd7\xdb\xf5\x77\xaa\x53\x4f\xe8\x98\xf9\x0d\xb3\xfb\x69\x67\x44\x30\x5e\xea\x90\x5f\xe1\x38\xea\xf7\x05\x4b\x92\x0a\x1a\xfa\x62\x49\x71\xfd\x18\x56\xec\x5c\x63\x63\xe7\x7a\x6f\x7c\xc5\x3f\xba\xb6\xcd\x30\x6b\xc6\xe9\xb6\x79\xd2\xdb\xf4\x28\x4d\x24\x13\x8d\x0f\x3a\xb9\xad\xa9\xc9\x8a\x12\xd0\x89\x46\x6c\xb7\x8a\xe3\x98\x75\xa6\xbd\x56\xab\x94\xa5\x41\x2c\xc6\x99\xde\x5f\x91\x55\xcb\x36\x86\xf1\xa8\x9d\x8c\x2b\x46\x4a\xd3\x5f\xce\x52\x17\x65\xa0\x1d\xaf\x3e\xb1\x55\x0f\xa0\x2a\xec\x7f\xae\x62\xd3\xee\xdf\xa9\x3a\xb7\xba\x22\x4e\x4c\x78\x67\x40\xfb\x43\xe6\xc0\x96\x57\xe9\xb1\xf5\x71\x15\xa6\x40\x2e\x3e\x39\x2b\x83\x2c\x32\x98\xdc\x97\xb7\x3a\xb4\x22\x03\xca\x2c\x1d\xda\xe6\xb8\x40\x8a\xca\x17\xa3\xcc\x73\x9c\x47\xe5\x32\xa5\xa0\x6e\x0f\xe0\x24\xcd\x22\xf1\x8a\x86\xff\x8e\xf2\x26\x18\xed\x2f\xa9\x6e\x09\x93\x6a\x3f\x5d\x5e\x48\xfd\x28\xa1\xc1\x48\xaf\x24\x24\x6d\x26\x50\x9d\x4e\x6c\xcd\x74\x62\xff\xca\xe9\xf4\x8e\x31\x51\x0e\xea\xf6\x9a\x41\xd5\x5d\xf4\x3a\x04\x9e\xcf\xa7\xaa\xb3\x6d\xc9\xd2\x90\x2d\x9f\xe1\xb4\x5c\x3e\xf6\xb2\xf9\xaf\x93\xfd\x71\x22\xa3\xdf\x5e\x07\xe7\x89\x62\x2b\x9f\x8b\x6e\x56\x7c\xc0\xa5\xef\x71\x16\x26\xfe\x0d\xd6\x2d\xf9\x4f\x4c\x24\x5a\xba\xe4\x26\xaa\x49\xed\xc8\xff\xa2\x06\x3c\x11\x94\x87\x57\xbf\xd9\x00\xe1\xd2\xb7\xab\x36\x8a\xff\x64\xd5\x69\x34\xea\x2b\x6d\xe1\xf7\x6b\x3f\xf9\x17\xd7\xfe\x31\x61\xe2\xf7\x6b\x3f\xfd\xd7\xd5\xfe\x22\xce\xc6\xf4\xf7\x6b\x7f\xf4\xaf\xab\xfd\x8c\x4d\xa3\xbf\x55\x79\xf0\xec\x5f\x57\xf9\xdf\x6d\x78\xf0\xd5\x36\x7f\x68\x6d\x9c\x9e\xbb\xc1\x04\xec\x15\x5e\xd9\x20\x63\x3e\x88\x86\x39\xfa\xf3\x82\x98\x49\x7b\xaf\x74\x00\xd3\xf0\x46\x51\xce\xfb\x0e\x38\xff\x36\x78\x38\x78\x38\x78\x5c\x7c\x1c\xc4\x5c\xb6\x07\x74\x1c\x8d\x94\xf0\x38\x8e\x79\x9c\x4c\x68\xc8\xca\x06\x7e\x2f\x6b\xe3\x16\x71\x97\xcb\x07\x31\x5e\xda\xa6\x4b\x73\x0c\x89\x70\x37\xfc\x94\x47\xf0\xd0\x22\x82\xa7\x88\x98\xd1\x76\x87\xef\x14\xf4\x31\xd3\xf0\x0b\xac\x16\x7a\x79\xdc\x1e\xa6\x52\x32\x91\x94\x64\x9d\xe8\xaf\x77\x53\xe4\x0c\x22\x36\xea\x27\x4c\xda\xfd\x7e\x1c\x89\x44\x36\xfa\xf4\xae\x11\x0f\x74\xcc\xdd\x8c\xb1\x9b\x62\x14\x66\xda\x62\xf5\xb6\xbf\x5c\xf6\x0e\xdd\x4e\xc1\x79\x1b\xf3\xbe\x92\xa5\xb7\x52\x37\x9c\x42\x2a\x31\x98\xf7\x1f\x52\xf3\xbe\x63\xee\x95\xd3\x9f\x0c\xc6\x17\xd5\x79\xa2\xad\x96\x2b\xad\xbd\xce\x49\x2c\x99\xdf\x38\xbf\x8a\x92\x86\xda\xab\x22\x3e\x6c\xa8\x47\x3a\x35\x09\x0a\x47\x71\x48\x47\x8d\x44\xc6\x82\x0e\x99\x22\xfe\x2e\x4e\x45\x23\x50\xaa\xaf\x91\x62\x0b\x63\x49\x2d\x18\x69\x86\xc2\x3e\xfc\x0c\xc1\x68\x9b\x67\xf5\xab\xe3\x56\x3a\x1d\xff\x34\x6a\xc8\x2b\xa3\x84\x3c\xd5\x81\x7b\xc1\xab\xe5\x80\xab\x5d\xdf\xe4\x7b\x12\x76\xfa\xa1\x57\xdb\xc0\x40\x02\x85\xad\xad\xb4\xb8\xa9\xbd\x2a\x30\xb0\x7e\x5d\x3a\x38\xa1\xe6\xd4\xff\x02\x71\x37\xdc\xae\x5f\xf0\x3e\x43\x57\x53\xd5\x80\x5d\xa0\x2e\xad\xdf\x22\x29\x8d\x76\x19\x7e\xc7\x2e\xfd\x6e\x4e\x17\x9f\x83\xbe\xe1\xec\xd6\x44\xc2\xbf\x5a\x33\x7b\xc6\x81\x5a\x0b\xd5\x79\x93\xbd\xdf\x71\x30\x98\x29\x34\x92\x4c\xb4\x03\x2a\xda\x45\x70\xa6\x3d\x99\x46\x99\x0a\xa1\x86\x3a\xed\x67\x47\x21\x29\xbc\x65\x7a\x4d\x4f\xe1\x3e\xfc\xaa\x4f\x49\x19\xc1\x02\xee\xd0\x68\x1b\x8e\xb6\x75\x2a\x2d\xb8\x45\xfd\x6d\xb8\xdb\x06\x73\xbf\xed\x25\xc6\x35\x97\x84\xc6\xf8\x92\xc1\x2d\x4a\xb6\xe1\x46\xea\x0c\x40\xdc\x0d\x23\xf5\xe7\x1b\xae\x47\xb4\x56\xa0\x6f\x25\x52\x1d\x05\x5f\x47\xe0\x38\x15\xf8\x87\xeb\x87\x60\x32\xb5\x13\x8c\x54\xa5\x88\x2f\x05\xff\xe0\x74\x1a\x28\xc1\x47\xff\xd3\x96\xf1\x70\x38\x62\x4a\x7e\x6a\x8f\xfb\xf9\xcb\x91\x36\xe4\x16\x71\x21\xe3\xa0\xbd\xdf\x98\xc8\xf6\x6e\x63\x12\xb4\x77\xeb\xd1\x27\x41\x2c\x65\x3c\x76\xc0\xe9\x4c\x6e\x1b\x49\x3c\x8a\xfa\x0d\x31\x0c\x28\xf2\xa0\x61\xfe\x73\x3b\x3b\xfb\xb8\x1c\xa6\x33\x8b\xad\xd6\x2c\x8f\xb6\x15\x25\x23\x25\x10\x94\xf7\xf3\x28\x88\x8a\x92\x32\x62\x42\x8e\x29\xa7\xc3\x72\x00\xb7\xeb\xa5\x39\x9d\x96\x02\xd7\xc7\x6d\xc4\x31\xfc\xdc\xc6\xab\xc4\xe6\x32\xff\xdd\x8e\x5f\x1d\xc5\x4c\x58\xac\xf5\xf5\xd2\x06\x12\xf1\x51\xc4\x2d\xa3\xed\x72\x8b\xd6\x38\x1c\x6b\xf1\x1d\x9c\xcd\x2a\x4c\x85\xcd\x1a\x76\x0c\x89\x92\x14\x8d\xc0\x58\x91\x19\x3f\xd5\x2c\x72\x75\x77\xf3\xb7\xda\xf7\xfa\x81\xb5\x1f\xb5\xef\xf5\x13\x6b\x4f\xec\xd9\xf4\x82\xa3\x48\x54\x8d\x34\xef\xc3\x4a\xe2\xa5\xca\x62\xcd\x9e\x3e\x6d\x83\x0e\x39\x0c\x5f\xe0\x96\x33\x8a\x82\x07\x41\x1c\xcb\x44\x0a\x3a\x69\xef\xb9\x9e\xeb\xb5\xe9\x68\x72\x45\xdd\x83\x76\x3f\x4a\xe4\x83\x30\x49\x4a\x00\x77\x1c\x71\x37\x54\xaa\xcb\xa7\x50\x0d\xe6\xa7\x6d\xe0\x06\x87\xde\xe3\xe8\x8c\x25\xf1\x98\xb5\xf7\xdc\x87\xae\xa7\x4b\xda\xaf\xcb\xc2\x3f\x6a\x85\xd9\x68\xdc\xee\x53\xc9\x26\x51\x78\xc3\x84\x2e\x58\x7d\x65\x8a\x7d\x0b\xeb\xda\x84\x51\x1c\xbe\xab\x5d\xfd\x31\x08\x37\x9c\xa9\x3f\x23\xdc\x2d\xb2\x01\xdf\x8b\xe2\x49\x2e\x65\x08\xa6\x16\xf7\x2d\x5e\x06\xab\x5e\x86\xd6\xcb\xa5\xbe\x7d\x1b\x22\xe1\x86\x9f\xea\xb2\x47\xb6\xa4\xd4\x52\x2d\x78\xe3\xcb\x50\x1b\x5e\x4a\x16\xb5\xe3\xeb\xeb\x17\x1a\xa2\x98\xd6\xe6\xb7\x5c\x54\x3e\xf3\xe2\x73\x34\x40\x3b\xda\xfc\xa6\x48\xca\xcb\xd6\xca\x94\xb9\x6b\xb6\x4d\xe6\x79\xc5\xe9\x97\x10\x04\x05\x02\x7d\x04\x78\x3d\xd6\xca\xf2\x5b\xd4\x91\x87\x56\x86\x99\xe2\x65\xa0\xaf\x78\x29\x04\x18\x93\x5a\xff\x5d\x08\x7f\x86\xf0\x22\x84\xaf\x21\xf0\x18\x44\x0c\x32\x06\x16\x43\x1a\x93\x67\x1c\x39\xe7\x34\xb9\x71\x30\xd0\x78\x5d\x12\xad\x34\x46\x45\x1e\xad\x2c\xdd\x56\xfd\xce\x28\x3d\xad\x4f\xf5\x96\x15\xbe\x83\xca\x4d\x76\xfa\x3a\x17\xf4\x45\xe8\x5b\xe9\x8a\x13\x5d\x02\xdd\xd3\x59\x79\xf1\x0b\xb3\xee\x3c\xa3\x84\xc1\x89\x58\x75\xc1\x54\x3c\x49\x24\x95\xcc\x01\x89\xe1\x3f\x4e\x84\xcb\xe9\x34\x1a\x52\x19\x0b\x37\x4d\x98\x38\x1a\x32\x2e\xcb\xcb\x8e\xce\x45\xd4\xd7\x66\xbd\x66\x73\x25\xb6\x2b\x9a\x5c\xe5\x81\x57\x12\xaf\x3e\x96\xd6\x15\x6e\x28\xc5\xe8\x4f\x76\x37\x9f\x0b\x77\xcc\x24\xcd\x1e\x93\xab\x68\x20\xf5\x73\xe7\x50\xed\xcf\xa9\x94\x31\x9f\xcf\xb9\x2b\xa9\x18\x32\xa9\x8f\x72\xc7\x33\x3e\x8a\x69\x7f\x3e\x47\xc2\x9d\x08\x7d\x1d\xf3\x33\x33\x17\x10\xd6\xc2\xc9\x95\x60\x03\x10\x44\x75\x0d\x70\xf2\x9c\x21\xa9\x8f\x02\xa1\x14\xf1\x66\x53\xb8\xc1\xcc\x4c\x17\x7d\xc9\x69\x10\x98\x1f\x81\xfe\x91\xb8\xd4\xfc\x4c\x5c\xda\x2b\x1c\x03\x7e\xe6\x89\x90\x0b\x73\xb6\x05\xc2\x27\xfe\xca\x08\x3f\x7d\xb9\x2a\x07\x5d\xb1\x54\x70\x8f\x7d\x73\x79\xea\x43\x5f\x5f\xb9\x1a\xee\xa8\x7f\x77\x34\x8a\x38\x4b\x76\x1f\xeb\x87\xdd\x05\x44\x31\x19\x71\x18\xc4\x84\x72\x08\xf4\x4b\x6f\x01\x89\x7e\x68\xef\x2c\x60\x14\x93\x24\x86\x69\x4c\x46\x31\x6c\xaf\x9b\x52\xf7\xf4\x99\x3f\x8d\x81\x3e\xd7\x91\xf3\x2f\xfd\x20\x06\xfa\x4a\xfd\x0d\x63\x5f\x00\xfd\xee\xbf\xd1\x29\xe0\xe8\x63\x3f\xcb\xbc\x46\xbf\xf9\x8e\x03\xa1\xf4\x8f\x81\xee\xe8\xa3\xdb\xc7\x3e\x87\xf0\xa5\xc2\x12\xdc\xf8\xc7\x10\x8c\x74\x0a\xb4\xa7\x5a\x54\xd1\x1f\x83\x3b\xff\x3e\x2b\xa6\x7f\x6a\xa8\x9f\xea\xcf\x53\x9d\xcb\xed\xa5\x2e\xa0\x8f\x57\x40\x70\xee\x7b\x8b\x05\x86\x71\xde\x9e\xab\xf5\x94\x3f\xd5\x34\x6b\x6a\x4b\x42\xb7\xfd\x71\x0c\xe1\x54\x11\xbf\xe7\x3f\xd3\x69\x56\x4d\xad\x6f\xfc\x20\xd6\x57\x18\xc4\xe4\x3e\x38\x53\x3f\x60\x12\xff\x46\xb2\x56\x0f\xda\x79\xd2\xd5\x98\x30\x0e\x77\x31\xb9\xa7\x43\x45\xf8\x77\x4d\xf7\xad\xfa\x7b\xa6\xfe\x7c\x50\x7f\xce\xd5\x9f\x97\x3a\x3f\xdc\xad\x6e\xc3\xc1\x02\x6e\xf4\xc3\xce\x02\x8e\xf2\xa1\xfb\x10\xaf\xbf\x47\xe1\xc0\xbe\x47\xe1\x79\x3e\xea\xd7\xfa\xe1\xd1\x02\x9e\xe6\x58\x5f\xc5\x1b\x2e\x4c\x44\x1c\x49\x73\x08\x33\x26\x2b\xf3\x11\x2e\x5f\x93\xca\xf1\xbd\x14\x77\xf7\x27\xa2\xb8\x15\x96\x88\xf2\x32\x26\xfb\xb2\x58\xc1\xd4\x72\x42\xfa\x68\x13\xc6\x0b\xf8\x1e\x93\x8f\x1c\xce\x63\xf2\x9a\xc3\x97\x98\x9c\xc7\x6a\x24\xce\x62\x72\x26\xe0\x78\x3d\x91\xf7\xf4\x95\x2f\x21\xb8\x52\x8d\xbd\x35\xad\x3d\x59\x3b\x20\xc2\x0d\x7a\x3a\x33\x61\x68\xb2\x25\xea\x0c\x42\x6f\xd6\x83\x9b\xa4\x86\xbc\x48\x68\x78\x12\xc3\xb1\x19\xc5\x8f\x9c\xc4\x2b\xf3\x01\x43\x08\x31\x44\x25\x75\xaf\x7d\x09\xf4\xb3\x1f\x03\xf5\xfc\x14\xe8\x81\x2f\x32\x62\x7f\xfa\x0c\x82\x53\x9f\x42\xf0\xde\x8f\x20\xf8\xe4\xeb\x94\xe4\x67\xeb\xaf\x8f\xbc\x0f\xfa\xaa\xa5\x6f\x15\x86\x77\x4a\x96\xc1\xf0\x39\x5e\x9d\x19\xf9\x21\x04\x3a\x33\xf2\xb3\x98\x0c\x18\x8a\x30\x44\x9b\xb2\x3a\x3e\x8b\x61\x86\x06\x26\x2d\x9b\xc9\x97\xf9\x3a\x26\x31\x87\x8f\xf1\xe6\x8b\x41\x62\x4e\x66\xe8\x75\xbc\xe1\xdc\xb7\x93\xf2\x89\x88\x43\x96\x24\xac\xef\xe4\xdb\x69\xc0\x50\x66\xae\xcd\xfd\x0b\xd6\x97\xec\x58\x9c\x93\xa4\x93\x89\x58\x2a\xb7\xb3\x24\xb5\x7e\x8c\x91\xf3\x91\xdf\xf0\x78\xc6\x1b\xf2\x6e\xc2\xfc\x86\xd3\xe2\x78\xa1\x96\x8d\xee\xcc\x3b\x14\x41\x99\x9d\xe5\xc9\x9d\x03\x9f\x63\xa4\xbe\xe9\x0f\x79\x5e\x97\xa5\xf7\x66\x5b\x8a\x39\x04\x0c\x9d\x09\x9d\xa4\xe5\x67\x6c\x90\x99\x54\x04\xb7\xb1\xfa\xb4\xa2\x7b\x82\xb1\x1e\x1a\x0c\x2f\xe3\xdf\xbc\xe4\xe4\xed\x86\xc9\x5d\xcb\x41\xaf\xc0\x3f\xc5\xd5\xbb\x1f\x79\x91\x73\x79\x7d\x56\x38\x9a\x5d\xc6\x97\x1d\x97\xc1\x76\x52\xbe\xec\xb4\x54\x76\xbb\xac\x0e\xe7\xd6\xbb\x3f\x70\x92\x2a\x79\x10\x5b\x65\xb5\x4e\x91\x5f\xaa\x60\x19\x99\x5f\xc6\x20\xe7\x73\x66\x22\xcc\x2b\xdf\x74\xe2\xab\xfc\x9b\x92\x72\xd4\x62\x87\x6f\x31\xf9\x14\xc3\x8f\xdf\xed\xa1\x27\xf1\xa6\x3c\xfd\x26\xa3\xd6\x50\x2d\x27\x69\x72\x69\xe9\xb5\xf1\x3e\xe7\xfd\xef\xe2\xf5\xd9\x44\x7f\xc4\xf0\x3e\x86\x5b\xf4\x24\xb6\x12\x83\x69\x69\x4c\xb3\xbd\x3f\x63\x82\xde\x85\x9a\x77\x7a\x2b\xd3\x1a\x9a\xdc\x82\x4a\xaf\x55\x4d\xef\xe5\x29\x0a\x3d\xc5\x5b\x6a\x69\xc0\xde\x19\x94\x2f\x62\xf2\x5a\xc0\xd7\xf8\x17\xf9\xdd\xcd\x90\xea\xc4\x63\xea\x6b\xaa\x24\x4f\x9d\xcb\x90\x42\xbb\x53\x64\x3e\xd6\xf5\x7d\x40\xa9\xce\xa5\x71\xe8\x65\xf9\xc5\x18\x84\x7e\xaa\xf3\x8b\xa5\x3a\xbf\x98\x50\x7d\x22\x81\xfa\xa9\x4b\x17\xb8\x9b\x12\xc4\x88\x46\xb4\x83\x7b\x28\xcb\x01\xdf\xea\x80\x24\xb2\xd5\x81\x0e\xf6\xb3\x77\xd4\x24\x85\x6f\x75\x30\xa4\x7a\xd4\x5e\x8b\x55\x9b\xc0\x8a\x5e\x99\xa2\xaf\xb1\x11\x5f\xed\x74\x6b\x6a\x55\xf2\x48\xb5\x5e\x44\xff\xcd\x53\x38\xd0\x36\x97\xb0\x32\x09\xcd\x39\x85\x14\x4c\xee\x74\x05\xa2\xc9\xa3\x3a\x0f\x10\xd3\x0d\x94\xd1\xea\x04\xcf\x22\x82\xa9\xbe\x8e\x04\x58\x44\x7e\x40\x1a\x91\x38\x05\xba\x12\xd8\xd3\xe7\x6a\x4d\x7c\x57\xb3\xb9\xf5\xe0\xe2\xaf\xe4\x36\x88\x2f\x1f\x98\x03\x5a\x5c\xdf\xe1\x48\x5a\x1c\x13\xc2\x75\xc2\x2e\x93\xf6\x39\x8c\xc8\xaa\xcc\x95\x8f\x0f\x4d\xf6\xc8\x55\x79\x27\xa9\x6c\x8c\xe3\x44\x36\x1e\x6f\x4c\x3b\x99\xdf\x82\x1f\x21\xc7\x73\x15\x67\x5c\x97\xf5\x72\x30\x8a\xa9\xac\xe5\xbc\x64\x11\xea\xb0\xdd\x3f\x84\x4e\xb9\x60\xa7\xaf\x84\x38\x22\xa9\x84\x28\xfa\x45\x4e\xfc\x46\x1c\x21\xde\x3a\xf0\xfe\x10\x7f\x1c\x78\x7f\x74\xd8\xae\x7a\x46\xb2\x4d\xb1\xfe\xa1\x90\xb3\x96\xbe\xdd\x6e\x50\xd9\xa0\x68\x79\x45\x58\x48\x38\xc4\x44\xac\x9f\x17\xe1\xdf\x63\x6d\x26\xd3\x9f\xda\xbc\x85\x1b\x2e\xf3\xb5\x74\x15\x5f\x4b\x0d\x5f\x33\x89\x38\xb5\x5d\xaf\xce\xdd\x52\x98\x21\x0a\x86\xff\x99\x0b\xd0\x21\x88\xd6\x5f\x77\x34\x30\xf3\xc9\x48\x12\x49\x44\x82\x08\x46\x9b\xc1\x9f\x14\xe0\xfd\x68\x29\x95\x75\xc6\x90\xd7\xf7\x11\xcb\xfa\x68\x6d\xff\xf0\x95\xab\x45\x6a\xf6\xaf\x17\x2e\x86\x69\x44\xfa\x11\x6c\x47\xbf\x79\xc5\xd7\x38\x22\xcf\x04\x5c\x45\x24\x48\x61\x18\x91\xb7\x30\x89\xc8\x11\x3c\x13\xcb\xf3\xbc\xd8\x4e\x8c\x49\xd7\xd8\xe1\xcd\x85\x01\xc5\xfd\x16\xa3\x14\x51\xeb\x56\x3f\x51\x36\x6d\xb7\xb3\xbf\x7b\xc0\x0e\xfe\x40\xac\xdd\x79\xfc\xd0\x53\x8a\x58\x96\xe2\x00\xa5\x87\xbb\xf3\xf9\x56\x3f\x45\x0c\xf7\x68\xbb\xe3\x53\xdc\x42\x53\xf5\xab\x3d\x4d\x91\x06\x2e\xa3\x75\x52\x35\x51\x45\x4b\xe2\x45\x26\xc0\xa4\xf5\x14\x17\xbb\x9d\x43\xda\xd3\x74\xf8\x22\x97\x5f\xac\x9b\x23\x1e\x1f\xd2\xf9\x7c\xe7\x31\x21\x84\x36\x9b\x59\xa5\x39\xf4\xce\xc1\xc3\x47\x7b\x6c\xbf\x6e\x4c\xad\x60\xdc\xf7\x1e\x3f\x3c\x28\x60\xca\x44\x19\x9e\x05\xf3\xf0\xe1\xc3\x03\x76\x50\xb7\x96\x57\xd0\x74\xbc\xdd\x83\x47\x05\xcc\xc1\x4a\x34\x9d\x5d\x6f\xef\xa0\xa4\xe7\xe1\x6a\x44\xfb\x07\xbb\x16\xd1\x8f\x56\x03\x3d\xda\xed\x1c\x3c\x2a\x80\x1e\xaf\xac\x6e\xc7\x7b\xfc\x78\x7f\xa7\x00\x2a\x73\x74\x54\x50\xed\xec\xee\x3f\x7a\x68\x41\x75\x56\xe3\x3a\xd8\x39\xd8\x2f\xbb\xa9\xb3\xb3\x1a\xd7\xa3\x47\xfb\xa6\x33\x6b\xc2\xa2\xcd\xf0\x74\xb4\xb0\x66\x78\xd7\x12\xa5\x26\x83\xe1\x62\x01\x33\x34\x8a\xac\x3f\x69\x84\xfa\xe8\x7b\x9e\xd7\x31\x4a\xd1\x1e\x86\x24\x45\x4e\xdb\xc1\xd6\xcb\x1d\xfb\xa5\xfe\xad\x3e\x6e\x58\x2a\x3b\xf6\x52\xb9\x8b\x7e\xff\xe6\xb7\x5c\xa6\x10\xd9\x95\xbf\x3a\x0f\x9f\x5a\x33\xc8\x03\xe9\xd2\x5c\x56\xdb\xb2\xee\xa8\x60\x44\xdf\x5b\x85\x18\xa1\xd8\x2d\xee\xde\x60\xd9\xe5\x2f\x33\x34\x8b\x40\xe8\x8b\x7f\x41\x9a\x3b\x5f\x6e\x23\xb2\x9d\xc2\xcd\x06\x95\x81\xff\x81\x14\x53\x6f\x99\x0b\x1a\x56\xec\x5d\xb5\xe4\x9b\x95\x2e\xb5\xff\x98\x5c\x99\x51\x96\xdc\x27\x45\xce\xb9\xb3\xdc\xad\xfe\xaa\xbe\xf6\xad\xbe\x86\x4a\x3d\x06\x67\x2a\x0d\x9c\xab\x10\x86\x11\x56\xef\x3c\xe3\xa9\xcc\xa1\xa7\xd1\x9a\x64\xf6\xaa\xdc\x37\x43\x48\x7d\x32\xdc\x44\xbf\x2a\xdf\x31\xe5\x5b\xa6\xfc\x4a\x98\x76\x06\xa3\xe6\xcb\xe5\x2f\xda\x56\x7e\x4f\x23\x34\x40\x51\x04\x1c\xbc\xfc\xff\x58\x49\xa8\xe6\x9c\xf5\x33\x81\xe1\x43\xb4\x41\x4b\x56\x42\x72\x45\x3e\x7e\x1e\xfd\xad\xbb\xdf\x8a\xab\x07\xad\xab\xd5\x74\x78\x94\x39\x19\xae\xa7\x52\x28\xf5\x2d\x1a\xf6\x15\x6a\xf9\x0a\xac\x83\x3e\x8f\xea\xa0\x8a\xa6\xeb\x15\x6b\x86\x70\xa4\xa8\xef\x40\xe8\x1f\x43\xdf\xef\x40\xe0\x7b\xaa\x11\x3a\x9b\xc2\xa2\x22\xd0\x6c\x4b\xa4\x31\xab\x2d\xfe\x18\xeb\x94\x2e\x6a\x07\x5b\x60\x78\xba\x0a\xf1\x0c\x5d\x47\x7a\x5b\x5d\xc2\xf1\x9d\xc1\x38\x05\x2d\xf8\x18\x24\x54\x21\x79\xbb\xac\xee\x9a\x4d\x48\x67\xb2\xb1\x91\x28\xad\xb4\x4c\x64\x2d\x33\xad\xd4\x0f\x98\x41\xa5\x95\xd3\x57\xd1\x1a\x15\xa0\xe0\x12\xed\x4e\xfd\xfe\x31\x60\xe6\x2a\xa1\xd3\x68\xfd\x5d\x38\x3a\x05\x65\xea\x6e\xcf\xe7\x4a\x69\x28\xde\x30\xf5\x86\xb9\x34\x4b\x5d\x99\x65\xf9\x34\x39\x3e\xed\x9c\x8f\x25\xb2\xec\xe2\x1c\xa6\x33\x7c\xb2\xa5\xd4\x90\x4c\x8b\xd0\x45\x6a\xc8\x3c\xf7\x26\x75\xfb\x40\xad\xa4\x90\x0a\x5b\x08\x69\x96\x93\x32\x26\x4a\x57\x89\x48\xaa\x93\x87\xa6\xfa\xc2\xd5\xd4\x65\xdd\x3a\x95\x35\x92\x62\x88\x8a\xdc\x97\x9a\x3a\x8a\x73\x02\xc3\x1a\x59\xea\x7b\x9e\xd5\x33\xa3\xb0\x68\x41\x41\x94\xc2\x47\x35\x51\x18\xbe\x47\xe4\x29\x9c\x47\xab\x2f\xbc\xa9\x5f\x15\x9b\x55\xa2\x00\x92\x18\x92\x18\x17\x37\x71\xd2\x82\x15\x4b\x9d\x51\x53\xea\x8c\x9a\xd2\x65\xdd\x22\x79\xd6\x77\xd5\x94\x14\xd7\x97\xd4\x14\x9d\x46\x99\xed\xe8\x0e\x9d\x9b\x11\x08\x31\xc4\xf5\x90\x36\x5d\x77\x96\xa9\x54\x7d\xad\x6d\x6e\x16\x9a\xb0\x44\x14\x63\x2d\xbd\x7d\x59\xd5\x3e\x49\x0a\x30\x73\x73\x8f\x1e\x82\xfc\x38\x6f\x79\x15\x68\x35\x1f\x69\x9e\x12\x54\x35\x50\xba\xfa\xba\xa0\xb3\x68\x8d\xa1\x68\x27\xb3\x43\x1d\xad\xd6\xab\x22\x06\xc3\x14\xce\x22\x73\x2d\xca\xf1\x1a\x2c\x8f\x21\xd4\x48\x4e\xd6\xd5\xb2\x0f\x43\x63\xed\x12\xab\xaa\x39\xd1\xec\xfa\x38\x42\x37\x12\x9b\x43\xbc\xb7\x4a\x6a\xd6\x5c\xf3\x4d\xa4\x74\xfb\xfd\x05\x7c\xae\xf4\x4f\xc5\xbe\xd0\x58\x5a\xf4\x9c\xcc\x50\xa4\x15\xdc\x7a\x4e\xe2\x80\x21\x96\xa5\xca\x80\x0c\xca\x54\x2f\xe1\x38\x42\x4c\x7b\xdd\xb8\x15\x6c\xaf\x39\xc5\x33\x93\xb7\x59\xb3\x07\x9d\xeb\x07\xde\x44\x9a\x67\x6d\x30\x7a\x18\xab\xdd\x1d\xfa\x1c\xe5\xa6\xbb\x37\x91\xbe\xe0\x29\xbb\xff\xf8\x59\x44\x0a\x43\x56\x9a\x38\x70\x26\x8c\x61\x8b\xf1\x7e\x72\x24\x1d\x78\x6b\x7e\xa6\x13\xc5\x9d\xfa\xd6\x9b\x44\x52\x21\x6d\x90\x41\xc4\x87\x4c\x4c\x44\xc4\xa5\xb6\x7a\xe9\x97\x79\xb6\xe2\x44\x9b\xcd\x7e\xe6\x66\x33\xca\x79\x2c\xb5\x71\x37\x71\xe0\x48\x9b\xd3\x6e\xd1\x53\x70\x86\x8c\x33\x41\x65\x2c\x3e\x9e\xbd\x71\xe0\x99\xd0\x5f\x6e\xa4\x29\xa4\x33\x2d\x14\xf0\x01\x43\x1f\x8b\x4c\x87\x18\xc3\xeb\xac\x21\x3a\x31\x8b\xa9\xee\x59\x84\xab\x54\x38\xf0\x33\x5e\x83\xeb\x58\x5f\x3e\x04\x1f\x57\xee\x8c\x84\xa3\x2a\xef\x97\xbe\xb9\xe5\x56\xe9\x3e\xaa\x17\x7f\x6e\x50\xca\x4e\x19\x7c\x8c\x74\x4e\x13\xa3\x97\xbd\x5c\x7f\x35\x63\x99\xc0\x1b\x19\x5d\x1a\xc3\xdb\x95\xc6\x03\xc6\xc3\xb8\xcf\x3e\x9e\xbd\x7a\x1a\x8f\x27\x31\x67\x26\x17\x3e\x7c\x52\xa8\x4f\x31\x7c\xdb\xb0\xbf\x6b\xef\xc4\xa9\x39\xd5\xaf\xcd\x84\x3f\xa2\x2c\xb6\x96\xfc\x87\x03\x3b\x3a\x8d\xe2\xd6\x7f\x38\xb0\xab\x9f\x88\x03\x9e\x79\x45\x1c\x7d\xa6\x09\x9e\x44\xe4\x3d\xbc\x8f\x56\x4e\x39\xdb\x26\x95\x12\x89\x04\x46\xf9\x9d\x63\xdb\xf8\x9e\xda\x77\x8e\x69\xf9\x94\xcf\xe7\x14\x52\xb5\xf1\x9a\x1d\x24\x75\x29\x84\x9a\xf1\x2b\x66\xaf\x75\xbb\xb0\x5c\x33\x5a\xdd\xd4\x45\x42\xc5\x44\xf5\xf2\x51\xbf\x04\x09\xdd\xcc\x04\x65\xe4\xd2\x77\x51\xf5\xca\x25\xb9\xc9\x04\x75\x8b\xde\x47\xe6\xb2\x10\x99\x29\xb0\x7f\x46\xeb\xcd\x80\xef\x14\x17\x5c\xc9\xa2\xa6\x11\x5c\xa7\x60\x62\x03\xb4\xf9\x4e\x73\x8c\x4e\x67\x01\x5f\x6b\x8a\x38\x5b\x49\x8e\x11\x10\xb4\x1d\x4f\x66\x06\x31\x8a\xcb\x3b\x06\xc4\xaa\x9b\x37\x18\xc6\xbe\xfe\xb4\x93\x5b\x14\x73\xcb\x5e\xa7\x76\x73\x00\x77\x83\x56\x47\x4b\x74\x6e\xf0\xbc\xd5\xc9\xaf\x10\xf0\xab\xa5\xb8\x4b\xcf\x5a\xf5\xa2\x22\x2f\x56\x5e\xe0\x81\x81\x0f\x54\xeb\x1e\x2e\x40\x0c\xd6\x0b\x87\xc5\xbe\x28\x2a\x17\xe1\xe5\x36\x96\x50\xdb\x58\xfa\xda\x77\x5c\xdf\xfc\x74\x12\xae\x7c\xfb\x33\x0a\x08\x5b\x71\x6d\x6f\x79\x55\x9e\x2c\xb7\x39\x03\x9e\x56\x24\xc6\x05\x06\x39\x58\x33\xac\x5b\x33\x24\x06\x5a\xbc\x73\xb7\x17\x18\xd8\x60\xfd\xf0\xcb\x41\x6e\x5d\x49\x07\x24\x5d\xe3\xd6\xa9\xae\x83\xd8\xb2\xcd\x66\x96\xd9\xd8\xb2\xcc\xe6\x66\x58\xd5\xdf\xb4\x62\x82\x5d\x74\x43\x82\x28\x41\x99\x15\x36\xfe\x95\x15\x36\xb6\xad\xb0\x4a\xee\x31\x16\x74\x3a\x20\xcb\xda\xc9\xb7\x08\x03\xfa\x1a\x92\x7b\xfa\xd5\xe7\x03\x08\x9f\xfa\xe8\x45\x48\xee\xc3\xa7\xfe\x6d\x0a\xe1\xb9\x76\xae\x9e\xf8\xb7\xe9\x02\xbb\xe1\x53\xf5\xe2\x45\xe8\x86\xe7\xea\xdd\x8b\xd0\x0d\x4e\xfe\x5f\xee\xde\x44\xbb\x69\xa4\x5b\x18\x7d\x15\xa3\xe3\x4b\x57\x75\xb6\x8d\x9d\x84\x49\xb4\x8e\x17\x24\x84\x84\x10\x02\x19\x08\xd0\x1f\x27\xab\x24\x95\x12\x25\xb2\x64\x4a\x25\x3b\x01\xfc\x2e\xf7\x59\xee\x93\xdd\x55\xbb\x4a\x83\x65\xc9\x49\xf7\x37\xfc\x67\xfd\xdf\xfa\x9a\xc8\xaa\x41\x35\xec\xda\x53\xed\x61\x0e\x2d\x90\xfb\x45\x95\x96\xd0\x8b\xb3\x15\x55\x3d\x74\x0d\x80\xbf\x78\x7d\xf6\x85\xe6\x6a\xb7\x1c\x94\x5d\x92\x05\xaa\xc8\xdb\x02\x0d\xb7\x06\x68\x87\x26\x1e\xb4\x8f\x6a\x77\xbb\x52\x4d\x94\xea\xe3\xb5\xc5\x5a\xa0\x46\x66\xf4\xb8\xb2\x76\xaa\x66\x84\x07\x20\xb0\x8b\x93\xa5\xb3\x65\x86\x56\x9c\x10\x9d\x65\x10\x85\xba\xd6\x80\x27\x15\xec\xa6\xe5\x30\x54\xf3\x5d\x63\x9c\xfe\xb9\xce\x80\x00\x64\xdf\x73\x7e\xb3\x7e\xd3\x22\x1f\xda\xdc\x5d\x72\x32\xa4\x30\x49\xc8\x90\x52\x90\xaa\xfb\x4a\xa6\x89\x41\x9e\x84\x62\xdf\xd3\x02\xde\x7e\x08\xfb\x1e\x7c\xce\x0c\xd9\xf3\x5a\xa1\x55\xcc\x29\x24\xc1\x4a\x65\xa1\x57\x80\x73\x10\xac\x94\x31\x3a\x33\x92\xa8\xa5\xea\x66\x5a\xa2\x4d\x02\xcc\xec\x87\xef\x66\xc4\x6f\x94\x6f\x5f\x67\x04\x89\x24\x72\xb2\x68\x45\x48\x5b\xeb\x1e\x67\xe4\xbd\x24\x99\xce\x79\xf7\x4d\xe7\x7f\x73\x83\x55\x6c\x4d\x3e\x92\xbb\xbe\xcd\x55\x9f\x33\xe2\x86\x38\x52\x37\xc4\xb0\xec\x6e\x88\xc8\xfe\xee\x11\x61\xeb\x04\x73\x81\x7c\xc3\x41\xa5\x6d\xeb\xa4\x98\xb8\x7b\xcc\xed\xc5\xdd\xeb\x79\xdf\x99\x99\x55\x85\x18\x0d\x67\xf5\x9f\x39\x85\x68\x61\x84\xcb\x9a\xf6\xbc\xfb\x4f\x8d\xd7\xb1\xac\x2e\x73\x20\xc9\x3b\x23\x7f\xc6\xdf\x14\x8b\x16\x04\xc5\x8c\xeb\x42\xc7\x62\xc5\xb4\x5a\x71\xc9\x7e\xd0\x0d\xf5\x64\xa5\xfe\x93\x95\xbf\xca\x3e\x6e\x89\x1b\xe4\x3d\x50\xaa\x95\xe5\xc0\xdb\x37\x6c\x67\x0e\xc2\x6c\x92\x1f\x38\x6f\x45\x53\x3a\x95\x8e\x49\x1d\x64\xfd\x23\x2e\x9e\x84\x49\xd6\x02\x6f\x85\x93\xa3\xc7\x4c\x1a\x55\x0a\x89\x13\xe7\xa7\x37\xb6\xcf\x33\x92\x3f\x5a\x73\x0b\xbc\xd7\x36\x0b\xc0\x3b\xb3\x2d\xb0\xc0\x1b\xd8\x7e\xa0\x50\xa3\xf5\xd3\x02\xef\xb1\x3d\x50\x48\x73\x4c\x55\xa5\x38\xe9\x7b\xaf\x55\xbd\xf3\x8c\xa8\xe7\x33\xaa\x6a\xab\xa7\x81\x6a\xa0\xdf\xba\xef\xa9\x6a\x76\x9f\x98\xe8\xcb\x69\x89\x6b\x4b\xbb\x3e\x9f\xe3\x87\x1e\x23\xd0\x27\x01\xb8\xc5\x27\xf0\xa7\xfe\xf4\x94\x44\x79\x89\x1a\xa8\x7e\xa9\xc7\xea\x16\x03\xd5\xdd\x50\xad\x39\xa2\x30\x55\x64\x64\x2f\x81\xad\x90\xbc\x15\x14\x8e\x32\x0a\xdd\xe0\xef\xe4\xca\x54\x9c\xea\xc8\x80\xb0\xa0\x98\x38\xdc\xe4\xcb\x1c\x07\xab\x18\xe3\x18\x83\x55\x52\xb8\x0c\xcc\x6d\xed\x45\xe0\xa4\x31\x4c\x82\x76\xe5\xe9\x66\x55\x79\x3a\x0b\x9a\x85\x42\x13\x74\x06\x6e\x83\xd5\xb9\xa3\x6f\x02\x63\x54\x73\x1d\x18\x13\x99\x97\x41\x6b\x52\xea\xe3\xa6\xa2\x8e\xb9\x40\x9a\xc3\xeb\x95\x33\xed\x6a\x3d\x12\xc6\x19\x2e\xe4\x80\xab\x55\xfc\x46\x2e\x91\x33\x25\x91\xb3\x3e\x2b\x78\xb0\x9e\xfa\xa4\xd7\xef\x3e\x7c\xa8\x1f\x98\x61\xca\xf4\x2f\x5f\x71\xe5\x61\x40\x54\x53\x0f\xf5\x3b\xb9\x75\xa2\x19\xcd\x5b\x45\xb9\xe6\x4d\x3f\xc4\xbc\x2a\xeb\xcb\x05\xa5\x4e\x35\x63\x4b\x9f\x83\xbe\xcd\xde\x5a\x5c\x91\x96\x74\x29\x39\x9b\x90\x26\xa5\x63\xb1\xf6\xad\x44\x6b\x7e\x0f\x6f\x7e\x7c\xa3\x10\xf2\x30\x0d\x89\x19\x7f\x56\x53\x05\xe9\xf5\xd9\x0a\x48\xa6\x18\xa1\x17\xcb\x2b\xa4\x79\x33\x4c\x80\x53\x94\x26\x0b\x23\x88\x9d\xa4\xaa\xcb\x3a\x0c\x21\xe9\xb3\x22\x39\xcc\x56\x40\x92\xbe\x8f\x97\x5e\xed\xdf\x9d\xc3\x5e\xd0\x94\x95\xb8\xce\x15\x9b\xf9\x56\x6f\x1e\xd1\xa2\x12\x18\x72\xc8\x1e\x72\xc8\x61\x40\x8e\x89\xa2\x68\x7f\x0c\x6a\x5b\xae\x1f\x16\x17\x40\x83\xc7\x8c\xec\x05\x98\x59\x4c\x2d\x82\x9e\x32\xeb\xfb\xd5\x09\xff\xfa\x95\xe4\xcb\x11\xaa\xe5\x10\xe5\x72\x84\x4b\x03\x0c\x16\x73\xe9\x1c\x86\x10\xf6\x19\x84\x7d\x17\xc2\xbe\x97\x7f\x2c\x54\xcb\x12\xd0\xf9\xea\xd1\x94\x16\xac\x87\xea\x9d\x4b\xae\x02\x58\x04\x6b\x34\x27\x6b\x5e\x3e\x35\xba\xbf\xb1\x7c\x17\xb8\x7c\x4a\xa0\x6f\xc8\x9d\x7c\x17\x4c\xc6\xa8\xae\xf1\xe7\x73\xe2\xe5\x64\x3c\x1f\xc7\x28\x4d\x6c\x5c\x0d\x59\x64\xdc\x61\x0a\x06\xbc\x6a\xf2\xec\xc3\xb0\x98\x9b\x59\x07\x3d\xc5\xf3\xa0\x51\xe3\xbc\xa7\x79\xb3\x17\x95\xe9\x62\xf8\x01\x5a\xe8\xd7\x17\xb5\x6d\xf5\xc4\x49\x73\x0a\x27\x41\xa3\x32\x43\x10\x23\xf0\x48\x5a\x0b\x25\x79\xae\xdf\xda\x3a\x39\x60\xa9\xde\xf8\xdc\x8a\x1b\x5d\x1b\x23\xad\x5a\x06\x49\x1e\x05\x4e\x26\x61\xe7\x0e\x66\xf2\x28\x20\x3f\xdd\x67\x4a\xec\x99\xd8\x84\x39\x19\x7c\x0e\x48\x5d\x6d\x76\x11\x00\xa6\x7e\x79\x56\x46\xf0\xd5\x5b\x33\x9a\x98\xec\x65\x5d\x59\x28\xc4\x14\x5f\xee\xdd\xd8\x02\xbc\x7d\x3b\x06\x6f\x03\x73\xe9\x3e\xb3\x25\xf8\xae\xfd\x60\x38\x37\x0a\xea\x39\x85\xf7\xad\x88\x77\x4a\x76\x02\xb0\xde\xbc\x3e\xb1\x14\x39\x82\xcb\x40\xf3\xc5\xef\x0c\xd9\xbb\x08\x08\xaa\xcf\x2c\x2e\x44\x22\x2c\xb8\x51\x34\x51\x11\xc1\xb3\x60\xc5\xed\x17\x11\xc6\x2a\x72\x3b\x70\xae\x62\x78\x1b\xac\x34\xb4\xde\x0e\x60\x46\xce\xcc\x3f\x5b\x1c\x62\x0a\x5d\x64\x44\x4e\xf8\x52\xc1\x44\x16\x79\x92\x4f\x57\xc8\xab\x6f\x03\xe4\x77\x3f\x09\x10\x70\x8d\x43\x21\x4d\x74\xc9\xac\x2c\xcb\xf4\xca\x7e\xe1\x8d\xae\xca\xc5\x1d\x4f\xe1\x97\x7c\x12\x8e\x79\x92\xc9\x0e\xbf\xf1\x38\xf7\xb9\x5f\xf7\xff\x7f\xcf\xe5\x2c\x11\xd7\x1d\xbd\x68\x2f\x2a\x6e\x57\x35\x69\x69\x1c\xc0\x15\x5e\xc1\x7c\xec\x7b\x01\x5d\xb3\x3a\xd6\x9a\xfe\xf1\x16\xde\x05\xea\xfd\x33\x5a\xbb\xf0\xb6\x4e\x63\x9e\x5b\xb8\x08\x9e\x4e\x92\x38\xe5\x9d\x40\x24\xe3\x0e\x9b\x84\x78\x8b\xd2\x67\x75\x6f\xe9\x03\x16\x05\x89\x18\x73\xbf\x93\x89\xc8\xd4\x41\xa7\x2d\x4d\x62\x7f\x34\x1f\xc4\x32\xba\x4a\x5c\x6a\x17\x75\xca\xb5\xd4\x5a\x3b\xcb\xb4\x7f\x41\x3e\x97\x53\x05\x28\xef\x15\xf7\x7b\x96\x90\xb7\xa1\xde\xa2\xdd\xfb\xf7\xbc\xba\xc3\x6d\xd3\xe1\x81\x01\xcb\x86\xcd\xcc\xeb\xc7\x6b\xd6\xa3\x25\xed\xab\xb6\x9e\x25\xab\x18\x1d\x4a\xe1\xd3\x0a\xa9\xf1\xb3\xbe\x57\xc4\xc3\xf1\xf5\x6f\x31\x80\xb7\xe4\x24\xd0\xc9\xd2\x71\x0a\xbb\x21\xf1\x30\xf8\x8d\xfe\x39\x0e\x88\x16\x00\x28\xdc\x48\x4a\xab\xa9\x49\x29\x7c\x5f\x1e\x58\xf5\xfa\x5b\x14\xd7\xdf\x0f\x86\xa5\x85\x17\x6a\xde\x35\x1f\x95\xe7\x5f\x34\x57\xda\xa8\xfe\x7c\x15\xb4\xe7\x67\xff\x1e\x34\x9b\xf2\xa1\xd0\xac\x87\xf4\x31\x70\x66\x31\x7c\x08\x9c\x4f\x31\xb1\x26\x5c\xa4\x61\x2a\xdf\x28\xd8\x78\x7d\x33\x61\xb1\xff\x32\x8a\x2c\xf8\x18\x50\xd8\x5f\x71\x4a\xcf\x0b\x31\xfc\x4d\x6b\xad\x13\x22\xe0\xa7\x27\xed\x1a\x13\x55\x0b\x0c\x73\x46\xfe\xd4\x80\x84\xb6\xa7\xdf\x96\x82\x71\xe7\x89\x19\xbb\x1c\x32\x8e\x19\x2e\x67\x64\x4f\x82\x12\x63\x62\x4a\xd5\x51\x38\xd7\xda\xcb\x2f\xc1\x1d\x4a\xea\x38\xbf\xeb\x8c\xdd\x95\x43\x76\xaf\xec\x22\x30\xff\x97\x00\xa6\x01\xc4\xfd\x5d\xa3\x22\x15\xcb\x4d\x8b\x5d\xbb\x41\x3a\xce\x2e\x90\x90\x1f\x23\x21\x3f\x42\x42\xbe\x0b\x89\x23\xfa\xe7\x98\x38\xe5\x5e\xc9\x19\x57\x27\x66\x14\xfd\x93\x3b\x53\x33\x66\xab\x53\x33\xb2\xbc\xd8\x24\x90\x84\x59\xa6\x28\xff\x52\xb2\x46\xb9\x90\xac\x31\xc1\x1f\x5e\x96\xca\x64\x8c\x00\x83\xb1\x27\xf8\xe8\x46\x12\x9d\x6b\x17\x73\x10\x7c\xab\xe5\x73\xe4\x74\x74\x44\x62\x58\xc8\xe9\xc8\xa9\x36\x4f\x97\xae\x12\x4c\x36\xe7\xc0\x5d\xe7\x4c\x10\x2b\x48\xbc\x2c\xb5\x28\x64\xcb\xcb\xdc\x7e\x6d\x7f\x4e\xf4\xb6\x85\x76\xdc\x67\x23\xcb\xb2\x45\xdf\x0d\x01\x77\xf1\x55\x60\x58\x71\xd1\x77\xaf\xe8\x48\xfd\x6b\x1f\x29\xe4\x7c\x95\x47\xaa\x99\x53\xb5\x1e\x48\x76\xa6\x92\x48\x97\x02\x77\x9b\xfd\x50\x4b\xf5\x41\x69\x1e\xd0\x38\x82\x77\x6a\xdd\x2a\x83\xe8\x06\x30\x09\x89\xa2\x7e\x6a\x10\x7f\xfd\x83\x1b\x8d\x13\x55\xfd\x0c\xe1\x73\x52\xb7\xd6\x32\x95\xd8\xfe\x62\xa5\x9a\xd4\x7d\x4e\x84\x29\x41\x85\xab\x6b\x3c\x27\x3c\xb7\x91\xfd\xc2\x1e\xcf\x6d\xcc\x90\xe8\x49\xda\x77\x47\x17\x44\x40\xfd\xe4\x52\x73\x13\x64\x52\xfe\x59\x98\x46\x45\xc1\x86\x45\x4b\x53\x86\x43\x22\xe1\x24\xd1\xfa\x9c\xa3\x04\x64\xdf\x53\xc7\x4c\xb8\xda\x61\xab\x58\x17\x66\xd6\x05\x21\xaf\xe7\xde\xf6\xd0\x41\xdc\xd8\x94\xcc\x29\x24\xee\x2a\xb4\x1a\xff\xe1\x0c\x4a\xa6\x73\x11\xcf\x76\x84\xc2\x30\xbd\xa1\xf6\x55\x56\xb3\x0f\xdd\xd5\x36\x4a\xd5\xde\x64\xbd\x37\x69\x2e\xc9\x45\x9f\x55\xfb\xc5\x90\xa1\x9e\xe2\x21\x25\xae\x70\xd0\x8a\x72\xde\x4b\x72\x4b\x42\x9c\x3f\xec\x68\x2d\xa2\xdb\x7c\x5f\x3f\xf8\x43\xe4\x16\x85\x87\x78\x45\xd4\xe8\xc1\xa8\xc6\xc7\xfb\x6e\x75\x84\xc5\xab\xbe\x5b\x60\x60\x5e\x11\x9d\x8d\x2f\x5f\x6e\x1e\xa8\x8a\x72\xae\x29\xaf\x62\x60\x4c\xdf\x92\xf1\x12\xf2\xcf\xc8\x9f\x59\x1f\x2f\xc4\xfa\xec\x5b\x01\xaf\x18\xbf\xc5\xcd\xbf\x98\x9b\x5a\xb8\xe0\x39\x6c\xa1\x29\xeb\xeb\x8b\x31\x4f\x37\x9f\xd7\xdd\x1c\xab\xfd\x3c\x7c\x58\x3c\xe6\x9d\x26\xd8\x69\xe8\x24\x26\x95\xaa\x8b\x52\xb6\xfe\x0c\x03\x56\xfd\x18\x6e\x46\x82\x56\xd2\x9e\x44\x09\x10\x1f\xb2\xfc\xc1\x83\x21\xdf\xf8\x23\x1e\xcd\x48\xe0\x82\xe8\x6d\x02\x53\x22\x85\xeb\x42\xbc\x36\x34\xbf\x31\xd1\x7d\xbe\x54\x85\xbf\xe3\xbc\x9c\x0d\x37\xb3\x28\xb4\x7b\x14\x52\xb7\x9d\x2d\x71\x5d\x6d\x6c\x81\xdc\x42\xd3\x96\x17\xd6\x17\xcb\xc4\x50\x67\x29\x96\x7d\x57\x1b\x50\xb9\xc0\xd7\x14\xd3\x9c\xb8\xc0\x7b\x08\x83\xfa\x94\xf8\xad\x9f\xd7\x89\x64\x62\x34\x21\x52\x35\xa7\xae\xf3\x01\xba\xed\xc4\xcd\xc8\xa8\xf9\x48\xf6\x85\x4e\x99\xdc\x18\xcd\xc0\x54\x7a\x70\x41\x74\xce\xf0\x87\x0f\x2f\x08\x37\xec\x07\x2a\xcd\x56\x2c\xca\xb9\x04\xbc\x0e\x36\xeb\x72\xe9\x36\xc9\xd2\x9a\x9b\xa1\x85\x46\x51\x0f\xb2\x8b\x9e\x6c\x5c\xbb\x35\xf9\x2e\xd9\x41\x41\x64\xec\xc2\x8c\x7c\x96\x30\x04\x49\xe1\x87\x49\x8c\x9d\x39\x68\x42\x0e\xc2\xd1\x69\xdf\x32\x90\xf4\xd1\xfa\xaf\x01\xc5\xe3\x3b\x23\xef\x12\x98\x91\xc8\x05\xa1\xb5\xb7\xcd\xfd\x65\xd8\x9f\x56\xc9\xc7\xce\xbe\x50\x5f\xcf\x9c\xf8\x51\xa6\x48\xce\x23\x09\x26\xc3\x4f\x9e\xb9\xb9\xeb\x12\x6e\x18\x46\x29\xe1\x8b\x24\xfd\xc7\x5a\x47\x0c\x98\x69\xf0\x56\x22\x8b\x5a\xda\x4f\x8c\x86\x8f\x36\x7e\x27\xd9\x9a\x5c\x23\x71\x4f\xd0\x47\x31\xb5\x07\x73\x0a\x17\xab\x90\x55\x8e\x1c\x72\x29\xfc\x01\xef\xb3\xbe\xfb\xeb\x57\x1d\x21\xe4\xc7\x98\xc1\xe2\x05\x36\x1a\x15\xa9\xe7\xdc\x1d\x23\x53\x2c\x68\xec\x78\x20\x1c\x0e\xd2\x39\x22\x52\x61\x7d\xa6\x48\x3c\x8f\x52\xae\xb1\xd2\x3e\x8a\x8c\x45\xe7\xe6\xea\x13\xa4\x62\x56\xe7\x14\x26\x6e\x93\x62\x71\x9b\xc4\xb4\x7f\x95\x84\x31\x92\x07\x98\xb5\xc1\x84\x95\x6b\xbd\xd5\x5f\xa1\xa8\xbb\xde\xfd\x51\x6c\x4f\x5c\x72\x4b\x2e\x5c\xbd\x0b\x7a\x6f\x0d\x06\xbd\x6d\xc1\xa0\x8b\x9d\xd1\x42\x45\xdd\x00\x53\xf9\x74\xd6\xfa\xeb\x8f\x7f\xef\x72\x32\x23\x33\x43\xa3\x7e\x27\xc3\x1e\xaa\x18\x6e\xee\x39\xe6\x41\x3e\xe4\xa1\x7d\x4b\x6e\x35\xa6\x9f\x91\x4b\xb7\xf0\x51\xbe\x76\x9d\x53\x78\xe9\x36\xde\x1d\xe5\x71\xc2\x0a\xb6\xe7\x69\x19\xe0\x8b\x57\x29\x29\xaf\x50\x52\xcd\x01\x5c\xd8\x52\x71\x00\xf7\xa5\xaa\xb5\x18\x20\xb7\xc4\xd3\x43\x3d\x21\x1c\x7e\xb2\xaf\xaa\x33\xb5\xfc\xbc\xcf\xbe\x82\x27\xed\x23\xc2\xfb\x1e\x82\x03\xda\x86\x29\xe9\xc7\xbd\xb6\x77\xe6\x8b\x6c\x12\x96\xbd\x58\xd5\x65\x56\xf4\x98\x73\x4a\x19\x55\x93\x91\xb5\xfe\x2a\xb9\xe4\xb0\xb9\x1b\xe9\xe9\x95\x2c\xd0\x66\xad\x06\x5b\x57\x35\xb4\xb7\x6d\xb5\xde\xe3\x7a\x4f\x5b\xf5\x9e\x36\xea\x3d\xed\xd7\x6b\x14\xd6\xe7\xcc\xc9\x27\xa3\xa6\xca\x30\xa7\xe7\x09\x61\xf0\xd3\xbd\xb6\x19\x86\x05\xf9\x4a\x47\x3b\xf6\x8c\x4c\x39\xc6\x5b\xd3\x2f\x58\xdf\xbd\xb6\x11\x71\x0f\x07\x3a\x8d\xd0\xb5\x0b\x37\xae\xae\x0e\x25\x9e\x6f\x14\x15\x5e\xa1\x42\x52\xad\xd0\x1c\x82\x8c\x82\xab\x3e\xe3\xed\xea\x3b\xa7\xea\x6c\x97\x22\xc2\x71\x64\xf8\x72\xcd\xd2\xb1\x6b\x0c\x22\x5e\xb7\x01\x32\x3a\xfc\x81\x77\xac\xaf\x23\xae\xdc\x55\x9e\x6a\xde\x4b\x5b\x80\xb7\xa7\xea\xbf\xb7\x25\x78\x43\x9b\xab\x46\x5b\xae\xf3\x55\xc0\x9e\xeb\x3c\xea\xff\xcf\x23\x38\x74\x9d\xef\x82\x0c\x1f\x0d\x28\x9c\xdf\x13\xde\x2b\x91\xf1\x36\xd0\x82\x8f\xf5\xbb\x23\x6e\xeb\x9d\xfb\x61\x23\x82\x3d\xc8\x40\x62\x00\x83\xea\x16\xd5\x01\x46\xfb\x57\xe3\xba\x7b\x12\xd4\xd4\x2c\x14\x75\xbd\x63\xdb\xb2\xe6\x90\xef\x06\xef\xbb\x3f\xd4\x3a\x16\x2e\xd7\x0a\xeb\xe6\x07\xe8\xd8\x1c\xa0\x5c\x48\x2a\x0e\xd0\xbd\x41\xab\x3c\x16\xec\xc5\xd2\xf8\xb2\xbb\x87\x97\x03\x4b\x7b\xa2\x6e\x77\x3c\x57\xa0\x94\x51\x6a\xe6\x42\x69\x23\xe4\xe6\x43\x44\xaf\xf2\x15\xc7\xc8\xdd\x5d\x3e\x1e\x4d\xe3\x37\xae\xea\xa6\xbb\x66\x9c\xe4\xde\xd8\x88\x14\x33\x23\x2a\x64\x74\x8e\x21\x94\x5a\x20\x75\x4e\xe1\x64\xb5\xac\x9e\x67\xca\xcc\x4d\x98\x3e\xbb\x2d\x7a\xdc\x22\x70\xd2\x73\x14\xc9\xd9\x1e\xca\xe4\xec\x1c\x42\xc5\xd7\xdc\x42\xa0\x7e\xed\x82\xeb\x64\x6b\xd6\x7f\x3d\xca\x75\x66\xa9\x23\x5c\xe2\x16\xa9\xef\x96\xf5\x89\x38\x79\x85\x6c\x77\x8d\xb8\x55\x2c\xd2\x00\x37\x3a\xc2\xeb\x20\xbf\x21\xa3\x66\x54\x8b\xea\x14\x3b\x11\x9a\x8f\x23\xf2\xf0\x76\xed\x53\x93\xfe\x13\x63\x33\x22\x43\xd2\xba\xe1\x97\x73\x08\x24\x35\x59\x42\xd1\x36\xb3\x2d\xbb\x4d\x89\x89\x77\x12\xb8\xd0\xba\x53\x0d\x6b\x99\xf6\x33\xb6\xe6\xc8\xa8\x05\x0a\xca\xbe\x06\x77\x7c\x54\x97\x4a\xe8\x06\xa4\x15\x51\x29\x1e\x03\x51\x15\xb2\x49\x15\xaf\xa4\x43\xc2\x90\x6e\x8b\x3a\xe1\x39\x24\x6e\x02\x6c\x39\xe6\xa5\x87\x6f\x97\x20\xe5\x0b\x27\x91\x9a\x05\x06\xb3\xa2\x2f\x96\xb6\xc5\x57\x23\xd8\xb3\x23\x60\xcf\x6d\xbf\xef\x2e\x62\x08\xb5\x30\x53\x67\x46\xde\x04\x20\x81\x51\xe8\x3a\x33\x12\xbb\x20\x21\x59\xea\x69\x31\x08\x84\xec\xb3\x8b\x51\x60\x7b\x18\x0b\x02\x7f\x78\x89\xed\x01\x3b\xb7\xbb\xea\x43\x53\x05\xb9\x48\x9b\xb1\x6c\x46\xce\xcd\x06\xbe\xe1\x10\x67\xea\x74\xec\x06\x28\x1b\x52\xbb\x2c\xdb\xcf\xcb\x7e\x98\x32\x28\xcb\x78\x86\x65\x07\x01\xe1\x55\x6a\x5d\x39\xcc\x42\x1f\x39\xa1\x8e\x5c\x4a\x4e\x88\x84\x9f\x98\x4f\x16\xad\x6e\xcb\x38\x65\x4f\x57\xb6\x38\x6e\x68\x31\x1c\xd4\x60\xdd\x3d\xa9\xc3\xfa\x26\x2e\xe4\xd8\x99\x91\x0c\xcd\x95\x20\x51\x4b\x39\x46\xc8\x1f\xf7\x5d\xb8\x74\xc6\x7d\x0f\x2e\x9c\x72\x3e\x42\xcf\xe7\x92\xc2\xd8\x49\xc9\x8c\x9c\xb8\xd0\xed\xbb\x57\x38\xeb\x0b\xc7\x1f\x55\x18\x1b\x1c\xdf\x98\xc2\xc5\x37\x4a\xed\x8b\xfa\xb6\xa8\x05\xc7\x88\x18\x14\x2e\x0a\x24\x7c\xe1\xdc\x90\x97\x2e\xb8\x68\x96\xc8\xd4\xc6\x5e\x3a\x17\xd5\x14\xdd\xba\xed\x73\x7b\xea\x5c\xe0\x4c\xca\x81\xc9\x7c\x60\x05\xae\x9b\x3a\x37\xe4\xbc\xec\x2c\x54\x9d\x4d\x97\x3a\x73\x6f\xed\x69\xad\x2b\x5e\xeb\xea\x59\x1d\x67\xbc\xae\xaf\xe3\x73\x5c\xc7\x49\x55\x01\x5a\x82\x1f\x9a\x7e\x4d\x40\xf4\xd9\x36\x1d\xcd\xc8\x7e\xf1\xc3\x9e\x91\x4f\xc5\x0f\xf0\x12\x8d\x80\x3f\x04\xe4\xc1\xb0\x82\x5a\x2f\x11\x13\x4d\x9c\x0d\xc7\x71\xc8\xc4\x39\x24\x81\x1a\x99\xa2\xa6\x0f\x1f\x4e\xfa\xee\x08\xf1\xcd\x67\x25\x85\xec\x0b\x32\x41\x6a\x4a\xa9\x3d\x4d\x96\x07\x32\x51\xdf\xb8\x2c\x20\xfc\x43\x40\x2e\xd5\xb4\x59\x02\x59\x06\x5b\x9c\x5c\x1a\x2d\xcd\x9c\xc2\x91\xeb\xcc\x62\xd8\x71\xab\xaa\x66\x0c\x09\xb8\xcd\x6e\x0f\x83\x33\xce\xaf\x2d\x38\x72\x29\xbc\x6f\x93\x3c\x63\xe0\xed\xd9\x88\xf3\xf8\x80\x8b\xb6\x26\x79\x74\xc0\x56\x8b\x93\x81\xc9\x36\xcc\x47\x45\xd5\xbc\xa7\xda\x64\xbd\xa9\xcd\x8b\x79\xea\x19\x4a\x35\xc3\x5d\x4e\xb4\x07\x00\x53\xe5\x94\xc2\x8e\x4b\x0a\x23\xb0\x77\x2b\xd9\x24\x93\x5b\xaa\xea\xf8\x82\xc1\x2e\x5c\x63\xaa\xf1\x55\xac\x34\xcb\x0e\xb4\x69\xfe\x9c\xc2\xb6\xeb\xcc\xc8\x57\xad\x85\x33\x9a\xe2\xbd\x6d\xeb\x1b\x45\xff\x9b\xb7\xae\x73\x13\xc3\x69\x2b\xed\xfc\x20\x49\xfc\x08\x25\xec\x1f\xee\xfd\x1d\xf4\xc4\x5a\x5c\x77\x09\xd1\x37\xfc\xbc\xef\xbe\x47\x27\xfd\xb2\x26\xd7\x1e\x51\x20\x1c\x91\xfb\xde\xed\xb6\x6e\x72\x95\x30\xfd\xd0\x18\x64\x46\x4e\x5d\xf8\x82\x32\xdd\x13\xbe\x69\x42\x77\x1c\xb4\x4e\x28\x66\x64\x46\x76\x8d\x48\xd5\x67\x9f\xe6\x14\x3e\xb9\xed\xd7\x17\x17\x21\xac\x6f\xea\x6f\x14\xcd\xe0\xc9\x00\xf7\xef\xeb\xea\x76\x43\xbe\xa1\xc7\x85\xb7\x3b\xab\xeb\x3e\x19\x94\xdd\xab\xea\xaf\xda\xd5\xda\x8b\xe3\x4f\xfe\x6f\x49\x42\x4f\xe1\xa3\xdb\x7e\xdb\x3c\xf8\x23\x1e\xdd\x92\x8f\x2e\xc4\xff\xfd\xdf\x43\x38\x22\x42\x6d\xc3\xf0\x61\x3c\x3a\x22\x12\x04\xb5\x25\xb5\x95\x2c\xf3\x61\x85\xc2\xe8\xa3\x96\x28\x51\xc7\x0c\xfb\x2b\xbe\x75\x44\x66\xe4\x83\x0b\x71\xaf\xcb\x89\xa4\xf0\x12\xb7\x50\x83\xd5\x9b\x15\xfd\xef\xab\xfe\xad\x01\xa6\xbb\xd0\x9b\xf8\xe5\x1e\x7b\x5e\xc0\xee\x90\x6f\x68\xa6\x2c\xbd\x1f\xe4\xba\x0a\x75\x7f\x17\xf7\x74\x44\x17\xa9\x33\x23\xdf\x05\x0c\x30\xd5\x52\xea\x08\x06\x5c\xbd\x3a\x0b\xe0\xc8\x05\x99\x52\xc8\xd2\x15\xe8\x44\x02\x51\x18\xb6\xf5\xd6\x6c\x92\xa5\x97\x44\x5f\x74\x8a\x39\xa5\xf0\xe7\xb7\xdc\x37\x57\xed\x0a\x4b\xef\x19\xe1\xc4\x4b\xdb\x77\x45\xdb\x30\x7c\x38\x3c\x36\x46\x0c\xda\x64\x19\x92\xe5\xbe\xe3\xfa\xed\x73\x91\x35\x44\x67\x0a\xd9\x47\x23\xd1\x43\x62\x99\xfb\x93\xd4\x82\x19\xc9\x52\x78\x93\x01\x11\x8e\xa0\x7d\xf7\x4a\x5f\x66\x95\x5e\x40\x3c\x25\x02\x73\x5e\xaa\xd7\xb9\xf7\x10\xbe\x64\x67\xfa\xa5\xce\xee\x81\x21\x74\x8e\x5c\xf5\xfe\xd4\xbc\x4f\xc6\x63\x1e\xcb\xfc\xed\xb1\xb9\x8d\xf3\x2d\x9d\xbf\xfb\xad\xab\x73\x7a\x1f\xe1\xc5\x93\x67\x32\xea\x08\x67\x46\x58\x0a\x16\x9b\x4c\xa2\x50\xc7\x89\x7a\x74\x95\x26\x98\xad\xf1\x75\x4d\xfd\x77\x1a\x90\x5b\xe2\xa5\xb8\x22\xdb\x5a\x45\x1b\xb6\xae\x37\x3b\x56\x8c\xc4\x31\xb0\x53\x1b\xd3\xbf\x4f\x6d\x01\xa9\x1d\xf7\x53\x60\x67\x36\xa6\x80\x77\x3d\x1b\x53\xab\xb8\x87\x36\x66\x86\x47\xb1\x76\x4e\x21\x68\x05\x8f\x24\x24\x08\xc1\x6b\x5c\x7b\xb0\x51\x70\x53\xa7\x51\x12\x90\x22\x1c\x13\x3a\x87\x34\x35\x4e\x39\x33\x0b\x9e\x0c\x36\x9f\xf1\xc7\xb8\x28\xbe\x05\x18\xb4\x00\x7f\x5c\x5a\xb0\xf1\xc4\x3c\x8f\x2d\x8d\xd9\xd5\x96\x58\x78\x50\xbe\x51\x88\xd2\x95\x87\xeb\xe9\x92\xaf\x1a\xbe\xac\xb8\x9d\xfd\xfa\xf5\x74\xae\x86\xfd\xb4\x77\x1f\xeb\xd4\xff\x44\xda\x3a\xb3\x7c\x7e\xda\x42\xfd\x32\x46\x62\x3a\x1a\xda\x83\x22\xde\xef\x5d\x36\xb4\x1b\xc3\xda\x30\x1f\x3f\x5f\x93\xb5\x91\x3e\x1f\xe4\xaf\x8a\xc1\x0e\xd7\x8b\x77\xc5\x80\x87\x8f\x87\xf9\xbb\x82\x36\x0c\x9f\x15\xef\x0a\xfa\xb0\x3e\x5c\xcf\xdf\x15\x34\x62\x7d\x73\x23\x7f\x57\xd0\x89\xf5\xa7\xc5\xbb\x4a\x30\x84\xc1\xe6\x9a\xac\xaf\xcc\xc6\xc6\xe6\x1a\x5a\x33\x4c\xd3\xbb\xb9\x94\x6e\x6b\x1d\xa6\x56\x6f\x6d\x46\x7c\x3c\x2b\x74\x4d\xe1\xcf\x71\xda\x46\x66\x97\x96\x76\xa3\x0e\x01\x7a\x37\xd6\x9f\xdb\xeb\xcf\xea\xb0\x50\xa7\xb9\x1b\x83\x3a\xd1\x1d\xd6\xc3\x57\x0c\xf2\xa5\xad\x47\xa3\xa8\x47\x9e\x18\xd4\xa3\x4c\x0c\x97\x17\x71\x69\x05\x91\xbe\x5e\xa6\x77\x5e\x08\xcc\xc8\x58\xaf\x0e\x64\x8e\xc7\x8c\xb9\xe4\x70\xfd\x0f\x27\xfb\xf5\xeb\x18\xbd\xbb\xca\x1b\xce\x9f\xec\x93\x2d\x81\x25\xb6\x00\x77\x68\xc7\x73\xc3\xc4\x25\x8c\x64\x6b\x43\x0a\xd2\x91\x3d\x64\x58\x2f\xd2\xf6\xab\xa5\x19\x99\x9a\xef\xe1\xf9\x14\xe6\xde\x67\x92\x1a\x0b\x20\xd6\xac\x52\x60\x89\x12\x9f\x4c\xa5\x49\xda\x50\x89\x78\xb8\xdb\xeb\xf4\xd1\xc6\x2f\x25\xf1\xdd\xb6\x9c\x29\xe0\x8e\x78\xd1\x76\xe6\xa5\x13\xaa\x35\x00\xc6\x88\xa4\x6b\xc3\x25\x9f\x80\x6e\x0a\xba\x02\x91\xce\x2c\x55\x0f\x09\x23\x1b\xbf\xcb\xde\x3a\x6d\x88\x02\x5d\xd4\x9e\xa8\xaa\x85\xd0\xb8\x08\x18\xbc\x37\x23\x51\x8a\x18\xbe\x06\x21\xa6\x64\x58\x94\x3c\xa9\x95\xac\x17\x25\x4f\x6b\x25\x1b\x45\xc9\xb3\x5a\xc9\x66\x51\xf2\xbc\x56\xf2\xb8\x28\x29\x01\xcb\x14\x3d\x51\x45\x35\x08\x43\xf2\x7d\xb3\x82\x7c\x1f\xa3\x09\xd5\x1f\x83\x51\x6c\x0f\xfe\x38\x46\xa6\x6d\x24\x90\x67\xbb\x5e\xd1\xaa\x7e\x66\x6f\xc9\x8d\x5a\x82\x12\x4c\x75\xec\x8d\x15\xac\xcb\x75\x0a\x98\x70\xd2\x00\xd9\x2b\x37\x7f\x3a\x28\x99\xed\xe3\x74\x95\x33\x8e\x22\x43\xbf\xc7\x6b\x4f\xf8\xe6\xef\x02\x83\x35\xc9\x35\x25\xea\xbd\x6e\xfd\xe8\x0d\x39\x56\x1f\xfd\x54\x7c\xea\x7b\xf1\xf4\xa5\x78\xfa\x5a\x7e\xfe\xaa\x0d\xdf\x23\x59\x35\xf4\x8a\xb8\x8a\xfb\x7b\xa9\x27\xa2\x96\xe4\xb5\x7e\xec\x49\xfa\xe8\x09\xdf\x44\x20\xdf\x4a\x5b\xef\x86\x5d\x05\x79\x6b\x12\x32\x67\x46\xae\x54\xcb\x24\x24\x1c\x39\x0d\xf5\xd0\x53\x93\xcb\x28\x9a\x22\x5c\xa5\x85\x69\xee\x05\xc9\xa0\xbc\xaf\x13\x2f\x78\x59\x59\x56\xbc\x37\x25\x98\x56\x9c\xd2\x11\x47\xa7\x87\xbd\x15\x7b\x7a\x4b\xb6\x52\xbc\xd7\xba\x4d\xd1\x7e\xf3\x65\x8a\xc5\x14\x06\x68\x13\xdd\xd4\xb2\x9e\x98\xa9\x38\x14\x39\x01\xd9\xb4\xeb\x9d\x9b\x5e\xa1\xdc\x0c\xfc\x89\x9b\x61\x9e\xbe\x98\xa7\x41\xa1\xbf\xda\xf8\xeb\xdd\x0c\x2a\xcd\xd7\xef\xdb\x7c\xb0\xd0\x6c\x58\x36\xdb\x4b\x61\x38\xd4\x81\x08\x16\xd1\x07\x16\xad\x57\x4a\x06\x0b\x25\x83\x4a\x49\xad\xbb\x4a\xc9\xc6\x42\xc9\x46\xa5\x64\x73\xa1\x64\xb3\x52\xf2\x78\xa1\xe4\x71\xa5\xe4\xc9\x42\xc9\x93\x4a\xc9\xd3\x85\x92\xa7\x95\x92\x67\x0b\x25\xcf\x2a\x25\xcf\x17\x4a\x9e\xeb\x92\x1a\x92\xd1\x13\x32\xde\x8a\x73\x0a\xe7\xed\xf0\x8e\x4c\x75\xca\x4a\x7e\xef\x27\x0b\x6d\x01\xec\xca\xce\x4b\x04\x05\x6f\xaa\x09\x58\x0c\xec\x3b\x6a\x6b\x6f\xd5\xe3\x0f\xad\x67\x39\x41\x21\xe9\x73\xba\x32\xe6\xe2\xb1\x7d\x86\xb6\x04\xec\x54\x3d\xc4\x14\xa6\xf6\x2d\x39\x4f\x01\x7d\x76\x01\x2d\x9c\x82\x14\x9e\xae\xf3\xc7\x08\xe1\x9c\x42\xaa\x2a\x22\xeb\x6f\x59\xc0\x19\xc1\x68\x4f\x94\x2a\xfe\xfb\x8c\x93\x93\x74\xb1\x05\x55\xfc\xf8\xb5\x54\xdc\xb8\x2e\x55\xbd\xe0\xbd\xc9\x9c\xc2\x51\x2b\x06\x42\xc4\xd1\xfb\x92\x11\xd4\xff\xec\xa4\x77\x38\xe4\x18\x03\xd2\x4a\x8c\x97\xf7\x69\xbb\x02\xc6\xd3\xb9\x27\x4e\xd1\x5d\x45\xc9\x12\x0e\x0a\x0a\x9e\x83\xf2\x43\xe2\x1c\x65\x24\x62\x44\xa6\x84\x69\x7b\x87\xe2\xb7\x57\xea\xf4\xcd\xca\x65\xf9\xca\xf1\x62\xe5\x4c\xfc\xd5\xfa\x32\xcd\xc8\x51\xaa\xfd\x26\xaa\x6b\xe5\xe9\x05\xd2\xab\x5d\xac\x11\xab\xac\xd1\x4d\xec\xb0\xd6\x00\xb5\xd5\x7d\xcc\xd4\x48\xb8\xea\x5a\xaa\x2e\x19\xb8\x57\x4a\x2e\xc5\x58\x02\x1f\x6d\x0f\xdc\x4f\x36\x46\x3c\xbe\x5a\x05\x0f\x6e\x60\x73\x70\x2f\x54\x17\x63\xd5\xfa\xb3\x16\x6b\x3f\x0a\x07\x03\x40\x84\xe9\xeb\xef\x19\x8b\x30\xf6\x43\x92\x20\x7c\x3c\x18\x98\x28\x0e\x61\x7a\xc4\x2f\xf8\x8d\x05\x89\x09\xe2\x30\x65\x51\xc6\xcb\x58\x13\xd5\x78\xab\x57\xfa\x02\x77\x47\x38\xd5\x30\xad\x77\x05\xa1\xcd\xf3\xd2\xfd\xa5\x00\xb4\x79\x92\xbb\xbf\x1f\x7d\xb6\x25\x3e\xec\x07\x63\x8e\xfd\x2e\x75\xda\x63\x70\x60\xd0\x8e\x1d\x13\xb4\x43\xc9\xcc\xf9\x6a\x14\x52\x75\xf1\xa2\x14\xbf\xf3\x57\xb5\x20\x1f\x4b\x21\x3d\x4a\xe9\xff\x2c\x21\x1f\x05\x8e\xf4\xa6\x0c\xba\x01\x67\x8d\x34\xac\x45\xb7\x60\x81\xf8\x56\xcd\x7a\x79\x9e\x80\x84\xd2\xba\xfd\x5d\xaa\x35\xbe\xdb\xa9\x43\x44\xe2\x24\x61\x3d\x58\x74\x4c\xae\x63\x22\x12\xb2\xcd\x24\xef\xc7\xc9\x8c\xe8\xcb\x58\x0a\x6f\xd3\xaa\x46\xdc\x44\x5a\xdf\x52\xb3\x4d\x84\xd6\x88\x9f\xa6\x77\xc5\x9f\xcc\x1d\x79\x4c\x5c\x9b\x91\x09\x31\x34\x32\x21\x92\x46\xc6\xd5\x6a\x34\x91\x64\x4a\x8c\x67\x4c\x9f\x01\x47\x73\x3d\x86\x99\x5d\xd0\x23\x85\x19\xcf\x94\xcc\xfc\xe5\xe6\xaf\x34\x7f\x0d\xf2\xf8\x2e\x94\x78\x7f\x43\xae\xd4\xd9\xb5\x2c\x78\x30\x34\x90\xae\xc4\xf6\x1f\xa9\xa3\x8e\x9b\x65\xa9\xf3\xa6\xfe\x3d\xb3\x75\xb2\x74\x83\xe8\xae\xec\xef\x42\x1d\x3b\x7c\x39\x87\xdd\x26\xf5\xce\xa1\x42\x28\x31\x85\x88\x21\x23\x8d\xc1\x67\xd0\x55\x4c\x67\x21\x28\x6f\x1e\x5f\xe0\x55\x66\x79\x45\xa2\x38\xcf\x2f\x78\x97\x89\x39\x58\x50\xb1\xa7\x10\xa0\xb5\xc5\xe2\xdf\x64\xc7\xe5\x9d\x30\xc6\xdc\x43\x13\x96\x4a\x4b\x23\x44\xd4\x26\x37\xa3\x43\xe6\x08\x85\x0e\xd1\xea\xed\x58\x9b\x74\x9f\xa2\x49\xb7\x7b\x88\xb6\x9d\xec\x2c\xff\xf0\x51\x46\x02\x72\x9a\xc2\x4a\xcf\xa1\x13\xf2\x23\x05\xb5\x38\x42\xad\x0d\xc6\xcb\xce\x16\x71\x11\xc7\x9b\xeb\x31\x4e\x7e\xca\x88\xec\xbb\x9f\xf1\x81\xe3\x43\xc4\x48\x86\x0f\x33\xb2\x9b\x82\x7a\x04\xa1\x7e\x23\xe4\x7d\x6a\x25\x02\xc7\xf8\x0b\x39\x73\xc5\xba\x7d\x6d\x27\xaa\xb2\x55\x52\xba\x25\x5f\x15\xab\x31\x5c\xff\x5d\x00\xaf\xd9\x2f\x04\x4c\xa1\x77\xe6\x0c\xd7\x7f\x57\xe3\x1b\xf6\x86\x74\x4d\x89\x67\x59\x9f\x25\x54\xfd\x10\xe0\x29\xa9\x51\xeb\xcc\xd7\x81\x51\x25\x3e\x32\x07\x65\x43\x06\xc3\x75\x25\x7a\x95\xf2\x00\x33\xf2\x80\x22\x06\x6b\x33\xf2\x49\xcd\x94\x7d\xd2\x22\x01\x12\x88\x1a\xe7\xc4\xd7\x9e\xfe\x2e\xea\x18\x8b\xaf\x21\x62\xfe\xde\x4c\xdd\x97\x02\xc0\x2d\xf1\x9d\x5a\xe7\xc5\xe9\x5a\x21\x24\x6d\xda\xb1\x33\x7c\x0c\xc2\xc1\x58\xb1\x26\x60\x4b\x43\x54\x8f\x8d\xbc\x1e\xca\x13\xed\xf5\xd6\xf3\x7a\x28\x7e\xac\xa8\x38\x5c\x60\x3a\x25\xe0\x56\x6c\xe4\xdc\xa7\x9a\x8f\x02\x88\xd7\xe6\x71\x89\xad\x2c\xdb\x0c\x57\xb7\x19\xd8\xb1\xb3\xae\xe6\xb7\xbe\x6a\x34\xa6\xd2\xaa\x25\xc0\x15\x18\x82\x70\x9e\x36\x57\x2a\x23\x9d\xac\xa8\x85\xce\x2d\x2b\x24\xb0\xef\xa9\x02\xa5\x58\x67\xca\x57\x24\xf8\x8e\xba\x1b\x95\xba\x1f\xda\x4f\xc0\x2d\x39\x4c\xf3\x48\x61\x85\xfc\xc3\x41\xd2\x91\xb4\xb1\xa3\x18\x97\x11\x1d\x14\xf7\x1b\x50\x57\xcf\xd1\x42\x40\x5a\x09\xb7\xb7\x3c\xd8\x37\x2d\x2d\xbf\x37\xb6\xac\x0e\xfd\x4b\xad\x65\x96\x5b\x74\x34\x28\x7e\xf2\x30\xb2\x7c\xc1\x12\x63\xb7\xc5\xeb\x44\x67\x0a\x98\x57\x3c\x82\xe3\xd1\xa1\x3a\xc3\x3f\x80\xab\x3f\x57\x94\xda\x87\x04\x1f\x7f\x50\xc0\x17\x73\x2d\x50\x8e\x03\xd0\x18\x1e\x0f\xfc\x8b\x76\xef\x8c\x13\x92\xc1\x4f\x96\x28\x76\xee\x92\x69\xdf\xc2\x9a\x44\x53\xa9\x81\x3b\xb1\xae\x26\xae\x57\x61\x08\xbd\xa1\xfa\x55\xbe\x97\x9a\x84\xd6\x20\x5e\x77\xf1\xbd\xb4\x5e\xa8\x09\x40\x79\xf9\xb5\x9c\xd3\xaa\x4f\x1f\x6f\x32\x2f\xae\x78\xe9\x5e\x60\x64\xee\xc2\x08\xfa\x45\x89\x28\x88\x50\x82\x3c\x96\xab\x05\xf9\x92\x11\xf5\x12\x1f\x70\xb0\x43\x1c\x77\xec\x28\xd6\x1e\x59\xf6\x1e\x32\xfe\x62\x4d\x7b\x57\xb2\xd6\xeb\xa0\x7e\x77\x24\xb4\x17\x05\xc7\x8b\x50\xad\x4d\xf0\x9c\xa5\x84\x46\x59\x9f\x7d\xaf\x85\x68\xc3\xad\xbb\x55\x5b\x12\x56\xd2\x5c\x83\xa2\xad\x95\x82\xc2\x07\x8b\xe5\xce\xf4\x45\xaa\x9f\xa2\x1f\x9d\xdc\xfb\x5a\xe6\x93\x5f\x20\xb8\x79\x31\x72\xe8\x74\x6e\xdc\xd9\x5b\x7b\xd0\x29\xb6\x2b\x56\xec\xe7\x21\xe8\xb5\x13\x7a\x71\x2e\x10\x2e\xe8\x08\x1b\x69\x09\x4b\x20\xe0\x2d\x7c\x86\x50\x48\x30\x6c\x96\xe7\x78\xe5\x85\xb1\xde\xd9\xd0\xf6\xb4\x14\xa8\x24\x00\x04\x53\x25\xf6\x25\x4a\xec\x53\xef\x12\x40\x00\x9e\x17\xd2\xaf\x76\x1d\x57\x6b\x13\xa0\x7b\x90\x8b\x9e\xfa\xed\x12\xd5\x1f\x83\xd1\xc0\x46\x52\x66\x0c\xd3\x13\xe7\x96\x08\x08\x21\x68\xbb\x3d\x8b\x47\x33\xf2\x26\x85\x19\x49\xe1\xc9\x00\x30\x72\xb6\x3d\x23\xfb\xfa\xcd\xfa\xa6\x7e\x33\x2f\x99\x4b\x3d\x8f\x2b\x3b\xe9\xbb\x6a\xd4\x09\x46\xb3\x2f\xd2\x3d\xe1\xf0\x02\xfd\xcd\xca\xb0\x97\x5c\x60\xf2\xd3\x2f\x17\x7c\xff\xea\x8b\xad\xd8\x61\xe4\x0b\x8a\xf8\x16\x33\x12\x8f\x3e\xa6\xf6\xab\x14\x5c\x0d\x70\x4b\xe3\x0a\xf4\xb8\x82\x22\x9a\x56\xd4\xae\x0b\xaa\x73\xa6\x13\xfc\x40\xce\x81\xd2\x26\xee\xf2\xca\xc4\x2a\x14\x91\xb3\x2b\x40\x46\xce\x81\x00\x1e\xb5\x5e\x78\x1d\xd9\xa2\xcf\x8e\xd0\x32\xbe\xef\x52\xf0\x6c\x81\xd1\xbf\x84\x0e\x1c\x06\xee\x6b\x5b\xe8\xe8\x5f\xa2\xcf\xd4\x68\xb3\xc8\xf9\x21\x80\x45\xce\xa9\x00\x2f\x6a\x3a\xf4\xb7\x84\x45\x30\x1c\x0c\x71\x83\x7f\xfd\xc2\x9f\x4f\x9e\x6b\xbd\x5c\x2e\x25\x63\x04\x2b\x2c\xd9\xdc\xc0\x08\xaf\xa6\xde\xe6\x63\xfc\x35\x92\x6b\x43\x5b\xe2\x35\x5f\x16\xe9\x08\xb0\x15\x6d\x9a\xa0\xa3\x9e\x28\xd7\x3c\x56\x40\x14\xb5\x6b\x38\x55\xb7\x4f\xf0\xf3\xa3\x19\xf1\x22\xc0\x3e\xd1\x19\xc5\x80\x92\x17\xe5\xb0\x18\x46\x2b\x6d\x1e\x39\x3a\x6f\x70\x6d\xab\xd1\x14\x49\x1e\xdd\xd1\x3e\x24\x60\x82\xc2\xbe\x10\x55\x54\xa7\x86\xce\x4c\xa4\x29\x9d\x8c\x41\xd2\x3f\x8a\x06\x71\x35\xda\x94\xf6\x6f\xe0\x51\x11\x7d\x34\x88\x56\x47\x79\xac\x26\xa8\x30\x85\x78\xd1\x18\xb5\x8a\x3e\x3a\x6a\xbe\x12\x5f\x12\x67\x46\x92\x08\x3c\x9d\xa1\x32\x0c\x48\x52\x5a\x9f\xe4\xb3\xba\x21\x41\x04\x0c\x01\xa1\xcf\x8e\x7a\x24\x59\x63\x18\xf3\x1d\x58\xdf\xa3\x79\xca\x89\xbe\x0b\x49\x73\xac\x2f\xc4\xbd\xba\x96\x57\xa9\x33\x25\xa1\x5a\x7a\x1d\x40\x44\x8d\xea\x45\xe1\x52\xd5\xbc\xae\x4c\x2d\xd3\x8b\xcc\x6c\x04\x0b\x09\x46\xf7\xc2\x0f\x6b\x29\xec\x45\x25\xd8\x0a\xc7\xa8\x06\xf5\xd6\xc5\x22\x67\x28\x9e\xe9\x65\x4e\x40\x3b\x81\xb7\x9a\x0b\x74\xb8\xf3\x93\xbd\xc3\x53\x46\x81\x7d\xb1\x63\x60\x43\x25\xfd\x64\x92\x82\xcb\xcc\x7b\x97\xab\x57\x52\x52\xf0\xb6\x6d\x01\x6e\xac\xdf\xcf\xeb\xf9\x1a\x34\x48\x3e\x2b\x22\xa5\x55\xac\x4a\xf1\x5c\x88\x92\x9f\xd7\x67\x69\x7d\xa0\xf3\xca\xd1\x11\xae\x18\xef\x7b\xdb\xc0\xfb\x2e\xc3\xa0\x49\x32\xd2\xe6\x74\x14\x62\x35\x39\x55\x1f\x55\xa4\xcb\xf5\x63\xe4\x64\x45\x04\xcf\xea\x2d\x9e\x3f\x6b\x6a\xc0\xde\xe5\x0d\xd6\x2b\x0d\x02\xe2\x96\x35\xbe\xa8\x7e\xb9\x7a\x1a\xc2\x21\x11\x30\xa8\x86\x44\x69\xad\x89\x7d\x0e\x07\xc5\x02\xa8\x36\xda\x1c\x6a\x4e\x61\x57\x68\x4b\x8c\x2b\xb8\xa2\x90\x46\xce\x42\xe8\xba\x2f\x52\x55\xf8\x3b\x71\xd8\x52\x13\x87\x2d\x4d\x15\xf3\x70\xd0\x10\xee\xc9\xfc\xb3\x1f\xc2\x00\x1a\x12\x98\x54\xa2\x87\x67\x61\x93\x95\xee\x5e\x46\xe2\x35\x9d\xbb\x4b\xf5\x94\x46\xe0\x07\x14\x23\x8a\x6f\xe1\xb7\xf3\xf0\x54\x26\xa6\x52\x14\x15\x31\x95\x0e\x04\x85\x9d\x94\x4c\x25\xb1\xce\x44\x12\x5f\x74\xfc\x4c\xa0\x51\x43\x47\xe7\x0b\xc7\x40\xdf\x7e\xb4\xd2\x7c\x9b\xf9\xf6\x38\x01\xf7\xb3\x1d\xa3\x0c\x3c\x8d\x4c\x9c\xa2\xee\x9d\xcd\x08\x46\x38\x45\x41\x58\x51\x18\x9d\xce\xd6\x9e\x46\x5a\x96\xae\x35\x97\x8d\xee\xc3\x7a\xe9\x23\x46\x98\x83\xfb\xc9\xd5\xb3\xec\xb3\x33\x14\xb7\xb3\x65\x8e\xeb\x96\xc4\x11\x1c\xa5\x28\x0a\xd4\x38\x2f\xd9\x4f\xfb\xee\xe7\x17\xb1\xc3\x19\xa9\xc6\xeb\x53\xec\x9c\x2e\x43\x5b\x4f\x52\xa1\xab\x12\x7e\xa6\xf6\x8c\xf8\x11\x64\x20\xfb\x29\xaa\x3a\xf1\xa7\xa2\x92\xee\x61\x85\x4f\x36\xf9\x63\xd0\x3c\x1c\x87\xe8\x1e\xe2\x10\x71\xc0\xec\xff\xc4\x50\xd9\x59\x39\x54\x76\x56\xe1\xc7\xdb\x86\xea\x39\x51\xa4\x87\x4a\x32\x3d\xb8\x20\x05\x0f\x4d\x9e\xd4\x57\x71\xcd\xed\x93\x14\x95\x50\x4d\xdf\x65\x8b\xdf\xcd\x16\xbf\xbb\x61\xd7\x9b\x74\x23\x88\xa2\x4a\x9b\x6e\x04\xbb\x69\x39\x1c\x6c\xad\x17\x5c\xd5\xac\xad\xf8\xe6\x42\x77\xec\x54\x7f\x33\xd6\xec\xcb\x69\x85\x8d\x5c\xaa\xd6\x8d\x60\x5a\xab\xf5\x64\xb1\xd6\xf1\x42\x67\xc7\x45\xb5\xa7\xcb\xd5\x8a\xce\xca\x5a\xcf\x6c\xed\xf7\xba\xb4\xdf\x87\x44\xf6\xa7\x4a\x6c\xc3\x3f\x57\xad\xea\xb3\x73\x5c\x03\x9c\x3f\xae\x4e\x29\x25\xa0\x9c\xb0\xc0\xe6\x9f\x93\x7c\x75\xb4\x06\x5e\x68\x57\x32\xbd\x94\xfa\xb7\x29\x89\x8b\x92\x28\x82\x06\x15\xbf\x00\xa3\x81\x5d\x86\x2a\xcf\x49\xfa\x9e\xda\x23\x8e\x6e\xbc\xee\xa1\x2d\x9c\xa4\xcf\xb4\xaa\xbf\xb8\x45\x4a\x1c\xe2\x55\xe1\x49\x43\x8d\x9a\xb0\x12\x95\x3c\x75\x7a\xbd\xfc\x4a\xc2\x1c\xe0\xc5\x0f\x15\xf7\x10\x1e\xae\x90\x37\xa5\xda\x06\x6a\x49\xeb\x8d\xb5\xf5\xc7\xd1\xba\x22\x5a\xe5\xa5\x54\xf5\x07\xd1\x6a\xb1\x19\x39\x48\x01\xfd\x4a\x44\x9f\x6d\x16\x81\x84\x6b\x36\xd4\x5d\xfb\x16\x11\xd6\x39\x05\xb6\x69\xcf\xf0\x79\x93\x82\xfb\xce\xfe\xc2\x89\xb5\x95\x64\x91\xdf\x89\x13\xd9\x49\x33\x77\x1c\x4a\xd4\x5d\x2a\x9c\x0a\x79\x6e\xe1\x4e\x98\x62\xf9\x2d\x97\x1d\x0c\xc4\xdf\xb7\x72\x1f\x9f\xac\x1a\xb1\x38\xb7\x4d\x7f\x67\x7b\x49\xc5\x8e\x39\x37\x50\xff\x98\xc1\x2e\xf2\x6c\x49\xaa\x83\x16\xc2\x5b\x3c\x81\xa7\xc6\x9c\xfb\x15\x9a\x73\xe3\x8b\x8a\xcf\xc1\x73\x73\xc8\x37\x1e\x38\x6a\x57\x14\x0a\xe9\x77\x47\x9f\x13\xbb\xb4\xd6\x97\x6b\xd5\x1c\xc9\xd6\x9a\x57\x39\xd5\x95\x31\x29\x39\xb8\x38\x25\xac\x6a\x06\xac\x9d\x13\x98\x19\xe7\x2d\x79\xe7\x1a\x4f\x12\xf7\x4a\xb1\x4c\xc7\x14\x07\xbe\x9d\x36\x78\x35\x34\x24\xbd\x44\x52\x5a\xa6\xbd\xec\x7b\x53\xb5\xec\x37\xe4\x73\x6a\x62\x6e\x78\x18\x7b\x55\x20\x58\x78\x3b\x36\xce\x41\x67\xc3\x6c\xf4\x1a\x14\x70\x4b\xce\xd4\x92\xe1\xec\xf5\x18\x3f\xe0\x5a\x2e\x99\xfa\x6f\x3c\x30\x82\xf6\x48\x35\xfb\x9c\x28\xa9\xb6\x61\x84\xc8\x16\x48\x93\x7e\x5f\xf1\x84\xda\x5a\x71\x69\xcc\x33\xf2\x3e\x45\x3e\xbd\x36\x52\xd1\x77\xdf\xcd\x61\xd1\x42\xfd\xcc\xa5\x15\x83\x15\xcd\x39\x37\x80\xa7\xb7\x0c\x9e\x7b\x1a\x0c\x59\x8c\x40\xe6\x87\xe9\x24\x62\xb7\x1d\x16\x04\x3a\x76\x11\xe6\xf2\x4e\x57\x02\x23\xb4\x80\x78\x01\xa4\xde\xb2\x87\xc3\x9e\x06\xd2\x12\x3c\xbf\xe6\xe0\x89\xbe\x32\x3e\xea\xc1\xaf\xe8\x72\x58\x8c\xb2\x83\x78\x85\x43\xa8\xaa\xb1\xb5\xec\xa4\xb5\xd4\x87\xda\x13\xb5\xd0\x63\x8d\xa4\x8b\x93\xe9\x26\x0b\x6e\x7c\x03\x83\x89\x67\xe4\x4b\x5a\x54\xec\x4f\x97\xdc\x86\x54\x57\x21\xae\xf9\x26\x24\x0b\x8e\x78\xc3\xa1\x9d\x95\x1e\x33\x7a\xa9\x12\x8c\x21\xbe\xe4\xe2\x82\xf7\x35\x0a\x16\x16\xd6\xe7\xbb\x5e\x9f\xa4\xc9\x7f\x2e\x77\x5f\x28\xe6\x8b\x36\x5b\xd1\xea\x50\x62\xdb\xaf\xdf\xbd\x3e\x79\xbd\x18\x4d\x6c\x12\x55\xdc\x0c\xf4\xdd\x9d\xf1\x31\x98\x45\x7f\xed\x26\xad\xef\x7a\x2d\x97\x69\x17\x11\x08\x98\x44\xfa\x4a\xe3\xf6\xaf\x74\xdb\x10\x7c\x6a\xe9\x96\xee\x2c\x21\x78\x51\x87\x2e\xdb\xad\x2b\x70\xa1\x43\x79\xb9\x1f\xb4\x77\xc5\x75\xd4\x68\x80\xfc\x92\xe9\xcc\x08\xb9\xcf\xeb\xa5\xbd\x2f\x48\x4c\x81\xdd\xd8\x31\xb8\x27\xfa\x62\xf8\x65\xd4\x6a\x7e\xb8\x9c\x21\x9c\x65\xf9\x45\x7d\x0d\x22\xdd\xa4\xa6\x26\xf5\x92\xfa\x36\x7f\x31\x29\x57\xe6\x14\x8e\x23\xe7\x8c\xfc\x39\x84\x75\x18\x7c\xa3\xf0\xba\x4d\x23\xd0\x90\x3e\xbf\x06\x6c\x37\xf6\x8c\xbc\x8c\x9a\xb5\xc5\xe7\x1c\xae\x23\x35\xdd\xe3\x88\xce\x21\xae\xf9\xdb\x2e\x9d\xc7\x73\xdb\x38\xd3\x69\xd8\x76\xf7\x10\xeb\xdd\xe8\x63\x7e\x4b\x6e\x91\x8d\x83\xeb\xe5\xa9\xe7\x24\x62\x4f\x11\x77\xc3\x9d\xf7\x5d\x8f\x2e\xfb\xd1\x6a\x56\xd3\x5b\x24\x1d\x79\xe3\xca\xd7\x34\xe5\xbb\x25\xb3\x08\xad\x04\xa6\x92\xbc\x54\xd2\x8c\x37\x2a\x69\x16\xaf\xd2\x2c\x8b\xda\x9f\x93\x92\xe4\x6d\x16\x87\x7d\xe1\xb4\x86\xc8\xa9\x30\x64\x5c\x3c\xed\xdc\x76\xc3\x20\xe9\x7b\x14\xd5\x13\xc2\xad\x75\x0a\xe8\xe7\x16\xe6\x7e\x6e\x9e\xc3\x96\xfc\xdc\x12\x0a\xea\x94\xd8\x0d\x48\x20\x9c\x63\x44\xcc\xe6\xa3\x5e\xf5\xc9\x43\x83\x86\x68\x85\xc1\x55\xfb\xee\x2f\xa1\xd0\xe1\x9d\x28\x74\x73\x79\xd7\xd0\x65\x7a\x19\xc7\x56\x69\x61\x05\xdb\xba\xfb\x36\x9a\x9e\xe8\x36\x76\x95\x1c\xa8\x32\x96\x11\x6e\x88\x62\x8e\xfd\x8e\x99\x26\x0a\x52\x11\x05\x9e\x13\x05\x14\xc5\xab\xca\xfd\xac\xc1\x8f\x4e\x8d\x6e\x88\xe0\x77\x96\x82\x84\x0c\x5e\xb3\x0a\xfa\x5c\xd5\xa2\xdc\xa3\x45\xde\x26\xd3\x9e\x6e\x3f\xc4\x4a\x93\xa2\x8f\x76\x0c\xec\xc4\x96\xe0\x9e\xd9\x1c\xdc\xaf\x1a\x53\x9c\x1a\x5b\x8f\x44\x84\x17\x61\xcc\xa2\x55\xa9\x77\x27\xc6\xb4\xe2\xfb\xaa\x24\xca\x68\x9f\xf2\x5d\x7d\xe6\xa3\xf1\xd9\x6f\x55\xa1\xbe\xb1\x05\x98\x7c\xbe\xb0\x6b\xc6\xc1\x7c\x5f\xf0\x34\x6d\xb7\x4f\xd1\x2a\x88\xd5\x16\x29\x82\x33\xff\xb6\xc9\x1e\x25\xe5\x52\x46\x35\xb3\x93\xdc\x22\xc5\x0f\x53\xe6\x46\xff\x54\x42\xe4\x2b\x6d\x8e\x33\xe1\x68\xfd\xb1\x2d\xc8\x59\x42\x76\x95\x8c\x92\x27\x63\xc9\x4d\x4f\x0e\x84\xce\xdc\xa2\x27\x57\x66\x6c\x71\x39\xf9\xae\xd3\x21\xef\x8a\x3b\x8c\x2f\x7e\xb2\x03\x5b\x02\x7b\x6f\x67\xc0\x0e\x6d\x0e\xec\x99\xcd\xc0\x45\xfd\xd9\x17\xbd\xa4\x07\x66\x49\x2f\x92\x4f\x5c\xa4\x61\x12\x97\x8b\xea\x66\x61\xe4\x6f\xa3\x75\xcf\xc2\xab\xd3\x94\x8b\xca\x2b\xc1\x62\xef\xb2\x9a\x96\x66\x1a\x2e\xf6\x33\xad\x74\xec\x72\x9c\xab\xb6\x71\xd9\x8a\x72\xeb\x1b\x19\xaa\x29\x1e\xe4\xe6\x35\x71\x10\x5e\x58\x70\x2a\x16\xda\xef\xc5\x41\x82\x8b\xa2\x2b\x45\x59\x8a\x11\xe1\xae\x54\x9f\x3f\x74\x9f\xb0\x17\xdd\xc3\x1f\x27\xe7\x0e\xb4\x0b\xfa\xfb\x00\x62\xd8\x8a\x16\xe9\xb2\x50\x74\x59\x5b\x83\x1f\x46\xab\xae\xc0\xb4\x00\xb0\x17\x41\xc1\x60\x5f\x31\xf8\xaa\x18\xec\x1c\x41\xb8\x1f\xed\x9f\x2e\xe6\xff\x98\x1b\xb4\x47\xe1\x3c\x6a\x8f\xce\xf7\x54\x47\x30\xda\x5c\xbe\xaa\x7c\x62\xb0\xc5\x94\x7c\x76\xe1\x5a\x1d\x72\x77\xc3\xb0\xf6\x1c\x24\xd5\x41\xa5\xea\x58\x61\x03\x99\x32\x2f\xb3\x3d\xf0\x3e\xd9\xa7\x9c\x20\x79\x62\x25\x6f\x87\x0c\x37\x24\xce\x94\xbc\x8e\xe0\x25\xa2\x8e\x73\xd3\xab\xc2\x0c\x9a\x6c\xd4\xfd\x4d\x4d\x77\x1f\x55\x77\xe0\x9d\xeb\x6b\x20\x8d\xf4\x0e\x38\xb0\x65\x9b\xd4\xbc\xe1\x27\x7b\x4b\x33\x87\x85\x04\xf0\x55\xfb\xa8\xe6\x2e\xaa\x35\x05\x02\x7a\x32\x3b\xb7\xe4\x2a\x02\x13\x50\x3c\x99\xab\x21\x76\xf5\xd0\xc2\xe5\xa1\x7d\xb2\x3f\x70\xa2\xc8\x53\xd7\x0e\xcb\x51\x7d\xaa\x8e\x6a\x60\x87\x0d\x08\xd4\xfb\x64\xbf\xe2\x24\xa4\xf9\xf0\x70\x37\x8f\x31\x47\x6d\xa8\xe5\xb8\x2d\x55\xbc\x28\x5e\x06\xcd\x1d\x7d\xe7\x24\xa0\x8b\xf3\xdc\xe5\xe4\x87\x7a\xdb\xe8\xe2\x9e\xb7\x7b\xbd\xc8\xbc\x6f\x36\x3b\xc1\xc7\x25\x1b\x36\x5c\x10\xf7\x0e\x13\x52\x2d\x6b\xf1\xba\x97\x95\xc8\x11\xcb\xc6\xc7\xe5\x60\xae\x92\x46\xfa\x39\x23\x87\x46\xe4\x28\x08\x67\xa0\x61\x52\x73\x1c\xee\x86\xfa\x4c\x96\xc3\x64\xd0\x04\x93\x78\x3d\x57\x40\xa1\x26\x83\xae\x06\x41\xdd\x89\x77\xae\x3b\x31\x20\xe8\x2e\xef\xf3\xb9\xed\x36\x03\xdd\x63\xdb\x55\xc7\x3a\x1f\x8e\xf7\xb9\xa5\x83\xcf\xa6\x03\xb6\xc0\xa9\xa5\x1a\xd8\x4c\x5b\x03\x66\xe9\x72\xeb\xae\x9d\x36\x43\xd7\xba\x9d\x3a\x37\xe4\xb2\xe8\xe2\x6b\x3e\x87\x86\x4e\xbe\x9a\x4e\x8a\x21\xd4\x41\xc2\x7d\xbe\xc4\xe8\xd4\xbd\xf3\xbd\xd9\x52\x95\xe7\xf5\x2a\x51\xbd\xca\x7a\x9d\x87\xf5\xc2\x4a\x95\x16\x29\x2d\x59\x64\xdd\x4e\xa2\xd5\xb9\x13\x67\x36\x87\x1f\xb6\x84\x4c\x27\xc4\xca\xe0\xa5\xa6\x38\x9f\xa3\x66\xff\x3c\xf7\xe1\x43\x62\x59\x9a\xf7\xd2\xda\x40\x37\xcf\x66\xd0\x67\xf0\x39\x42\xf5\x08\xb5\x77\xe6\x70\xd4\x8a\x92\x6f\x64\x7e\x73\x38\xd2\xa1\x6e\xed\x3c\x1d\x82\x09\x44\xbc\xb3\xf8\x71\x29\x6e\x2b\x4d\x7d\xde\x90\xfa\x8b\xce\x3d\x66\xd8\x86\x22\xcf\xd2\x7c\x0e\xef\xdb\x50\xb8\x8e\xfa\xea\x58\x26\x31\x9d\x54\xf3\x92\x3a\x30\xe0\x03\x99\x47\x05\x8c\x1d\xf5\xc8\x40\x3a\x3b\x11\x5e\x31\xe7\x77\x73\x95\x34\x87\xe2\x85\x44\xff\xf5\x58\xd5\x89\x17\x2e\xdf\xb4\xf1\x85\x8e\xf6\x0b\x47\x91\x0e\x8f\x52\xcd\x20\x40\xe1\x5d\xeb\x1a\xb5\xc4\x67\x7f\x10\x97\x0e\xf4\x26\x93\xd4\x62\x8e\x00\xd1\xcf\xf2\x08\x8d\xb4\x5c\x33\xbc\xda\x78\x91\xc7\x2c\xe3\x7d\xf6\xf0\xe1\x62\x14\xb7\xa2\x4e\xec\xc8\xf9\x9c\xc4\x64\x4a\x4e\x22\xd8\x59\x72\x90\xdc\xd3\x34\xba\x9c\xa8\xde\xf1\x87\x0f\x75\x94\xb2\x3e\x1b\xc5\x7d\xd7\x8e\xe9\x5c\xc9\x92\x92\x82\x5a\x07\x82\x39\xb3\x8f\x68\xbf\x3b\x8a\x12\x1b\x03\x0f\xbc\x8f\x20\x4a\x4c\xe8\xdd\x87\x96\x46\x95\x6a\xf7\x1f\x43\x26\xb5\x6c\x7d\x16\xad\x48\xf7\x90\xb3\x4d\x17\xb6\x84\x73\x05\xb8\x37\x36\x87\x23\xdb\x83\x63\x9b\xc1\x89\x9d\xc1\xae\x06\xe2\xed\xe8\x2f\xe4\x41\x93\xa4\x88\xd3\x2b\x02\xa3\x64\xc6\x5c\xfe\x2b\xf4\x1c\x27\x11\x88\xfe\x4b\x10\xfd\x0c\x44\xff\x07\x88\xfe\x0c\xf2\x7b\x24\x4c\x4b\x18\x2d\x64\x6a\x2f\xf2\xb4\xb7\xe7\x1f\x8f\xfb\x2f\x71\x2b\x33\x34\xa0\xff\x81\xf6\xf3\xb3\x17\x55\x99\xf9\x2d\x2e\xf8\x67\x0a\x9e\xde\xa3\x92\x9b\xd4\xc3\x6d\x4e\xed\x38\x23\xdb\x11\x7a\xd2\xec\x25\xb0\x93\xc1\x6e\x48\xf4\xc5\x1b\x83\x49\x48\xac\x80\x45\x29\xb7\xb4\x4e\x1d\x4e\xa3\x15\xd1\x33\x1a\xd3\xcb\x17\xdf\x78\x97\x28\x7a\x82\xc7\x71\xe5\x4d\xf2\x8c\x9c\xaa\xd1\x10\xe9\x88\xc6\xeb\xcb\x1f\x95\xa8\x9e\x38\x49\xb5\x2c\x6a\x51\x04\xc4\xfd\x19\x10\xbc\x36\xfd\x4c\x09\x5a\xf6\xd0\x6f\x68\x61\x92\x3b\x92\xef\x56\xe6\xef\xad\x48\x34\xd7\xb8\xd2\xda\x51\xe1\xb3\x41\x09\x1a\x03\x60\x66\xbd\x92\x2a\x5c\x90\x18\x3c\x3a\xca\x47\x56\x24\x72\x29\xb6\xe1\x9b\xc2\x7e\x45\xd4\xce\x39\x1c\xac\xd8\x8f\xc6\xf4\x29\xae\xc1\xab\x79\x2a\x44\x94\x55\xe7\x4a\xbc\x9b\x91\x2d\x38\x53\xdf\xfc\x2e\xee\xf8\x67\x57\x90\x3c\xa0\x3a\x85\x83\x22\x32\x33\xc5\x1f\x3a\x00\x33\x5e\xb2\x6c\x47\xb0\x14\x82\x39\x07\x92\x09\x26\x02\xa5\xba\x4d\x11\xc8\x99\x2a\x10\xab\x84\x93\x36\xbf\xcb\xd8\xd1\xe6\x85\xf1\x17\x30\x62\x9e\x1a\x8f\x92\xd8\xc2\xf8\x42\x8d\xa8\x96\x60\x30\xf9\x67\xf7\x49\x9f\x2b\x8d\x87\x31\xeb\xaa\x93\x10\xcf\x60\xf6\x02\x55\xef\x68\x54\x5d\x87\x2d\x13\xb1\x55\x50\x88\xf5\x0e\x12\x89\x30\x55\x6e\xa1\x92\x06\x67\x4a\x9c\x39\x3e\x39\xda\x7b\xff\xc6\x82\x1b\x89\x22\x3a\x82\xf1\x6e\xb9\x18\x6a\x66\xf8\xee\x0a\xdf\x72\x3f\xd4\xd7\xd6\xdb\x62\x31\x65\x6a\x5c\x1a\x8b\xc6\x90\x39\x72\xe5\x99\x12\x80\x4e\x43\x59\x7e\xaa\xc2\x15\x7e\xfb\xf9\x4d\x99\xa0\xe0\x5e\xd9\xb7\x6a\x1f\xbf\x04\x64\x1a\x50\x18\x07\x64\x87\x9a\xf4\x8e\x61\xcb\xc0\x0d\xd8\xc4\x7c\x66\x51\xb8\x25\xdb\x02\xc2\x2a\xe8\xa8\xe7\xdc\xa7\x42\x43\x05\xc2\x63\xc3\xa0\x5d\x72\xa6\x80\xfb\x5a\xc2\x83\xa1\xfa\x37\xff\x3f\xe6\x64\x32\x5f\xa9\x7c\xb9\x0a\x9e\x7a\xa9\x97\x47\x77\x85\x07\x1b\x5f\x6a\xc1\x90\xc2\x8f\xc8\x21\x32\x71\x50\xe1\xb5\x05\x1f\x39\x1c\xa8\x49\x6c\xc1\x56\x82\xe6\x11\xea\xf1\x2a\x81\x03\xf3\xf8\x8a\x43\xa8\x9f\x3e\x70\xd5\x9b\x7a\xfa\xce\xe1\x87\x29\x3e\xe5\x70\x6a\x1e\x75\x14\xc3\x86\x69\x69\x5e\x65\x4e\xbf\xd1\x26\xdb\x08\xc4\x7e\x4d\x2c\x13\x9a\xbf\x48\x94\x28\x77\x23\xe7\x95\x80\x83\xc8\x44\x4a\xfc\xa4\x0d\x14\x36\xe6\xf0\x55\x3f\xad\xcf\xe1\xbb\x7e\x7a\x32\x87\x57\xd1\x7d\xb2\x41\x6d\xb5\xd8\x21\x8f\x81\x3b\x7b\x4c\x47\x91\x9d\x91\x57\x91\xb6\x43\x0a\x13\x9d\x04\xd7\x9a\x88\xc4\xcf\xb0\x91\x05\x49\x82\xb1\xd4\x94\x64\x3a\x52\x54\xdb\x56\x14\xde\x6b\x6a\x75\x51\x8b\xeb\x9f\xb7\x4c\x9c\x3c\xf6\x91\xe3\xe8\x76\xf9\xef\x6a\xeb\xa0\x16\xaa\xe9\x46\xb7\x1e\x0d\xed\x01\x84\x0d\x71\x99\x78\xc5\xba\xa2\xe6\x01\xbd\x94\xda\xa2\x73\x9b\x98\x38\x4c\xfa\xf3\x0b\x1f\xf6\x6b\x1e\x31\xe6\xc3\x90\x39\x6f\x39\xc9\xe7\x7c\x29\xe5\xc4\x7e\xf4\x28\x4a\x3c\x16\x5d\x26\xa9\xb4\x9f\x0f\x9e\x6f\x3c\xb2\xaa\x1a\x87\x08\x0e\xb5\x2b\xf7\xd8\xf9\xa9\x6f\xda\x76\xf0\xde\x4c\x96\xda\x68\x37\x01\xf7\xc4\x1e\x56\xe0\xa7\xbb\x8c\xdb\xa6\xcb\xaf\xfc\xe5\x57\xd1\xf2\xab\x74\xf9\x95\xbb\xfc\x2a\x58\x7e\x15\x2e\xbf\x6a\xc0\xb9\x0d\xe4\x92\x2d\xbf\xca\x96\x5f\x35\x24\x74\x6d\x60\xb5\xc4\x0a\xee\x4b\x89\x9b\x3e\xb8\x9b\x76\x08\xee\x53\x3b\x00\xf7\xb9\xed\x81\x17\xda\x1c\xbc\xc8\xce\xc0\x4b\x6c\x09\x5e\x66\xa7\xe0\xcd\x6c\x86\x77\x95\xe0\xbd\xb1\x13\xf0\x3e\xd9\x11\x78\x9f\xed\x18\xbc\xaf\xf6\x14\xbc\x73\x7b\x0c\x5e\xd7\xee\x82\xfb\xd1\x76\xe7\xf5\xff\x2d\x5e\x96\xe6\x3b\xf7\x60\x08\xee\x3e\xde\xc8\x91\x19\xb9\x4c\x30\x5e\x9f\x7a\xec\xaa\x47\x8f\x52\xc2\x29\x09\x29\xb9\x48\xa8\x66\x6a\x49\x46\x09\xa3\xc4\x4b\xca\xff\x62\x4a\x3c\x4a\x24\x25\x3f\xbd\xa9\x9d\xcc\x35\x0b\xfb\x4a\x38\x6f\x63\x05\x22\x1f\x5b\x4f\x72\x29\x26\x88\x35\x62\xd9\xd6\xda\x55\x91\xd0\x07\x3e\xac\xb2\x89\x35\xe2\x93\xb4\x8f\x88\x84\x23\x52\x8a\x4e\xfb\x51\x3b\xd3\xe5\x29\xd2\x73\xe4\x9a\xc8\x43\x6f\x22\x67\x3f\x22\x96\x17\xb1\x34\x7d\xcf\xc6\xdc\xa2\xf0\x25\xca\x1d\xaf\xdc\x2b\x25\xc2\xc5\xbe\xf3\x26\x26\x96\x1f\x4e\x2d\x0a\x42\xff\x48\x27\x2c\xb6\x28\x48\xdf\xd9\x8f\x81\xfb\xce\x8c\xc4\x3e\xec\x00\xa2\x61\x61\x9e\xa4\x4f\xac\x77\x09\xf3\xc3\xf8\xa2\xdf\xef\x5b\xf4\x9b\x0e\x59\x93\xf9\x4e\x2c\x80\xf9\x2d\x91\x5f\x92\xd3\xc9\x84\x8b\x2d\x96\x72\x42\xe7\xe0\xf9\x7f\xe1\xde\x4b\x5f\x7a\xe5\x1a\x82\xc5\x8b\x02\xee\xd7\x71\xc5\x7b\x56\xdc\x74\x25\x7a\x52\x6e\x26\x65\xa2\xa6\x15\xfa\xf7\x0c\x96\x14\xe8\x86\xa1\x45\xc1\xf5\x9d\x4c\x40\xea\xb7\x2f\xbc\xeb\x43\x0c\xa6\x07\x81\x36\x65\x91\xef\x30\x01\xbe\xdf\xb0\xc5\xb1\x13\x8f\xac\x80\xf5\xc6\x61\x9c\xa5\x96\xad\x1e\x27\x51\x96\x5a\x95\xcc\x99\xbe\x5a\xe4\x33\xc4\x45\x6f\x22\x62\xb9\x32\xee\xb8\x32\xee\x25\x99\x8c\xc2\x98\xf7\xc2\x38\x48\x3a\x6e\x22\x7c\x2e\x7a\x83\xce\x58\xf4\x86\x9d\xb1\xdb\x1b\x22\x91\x8f\x7c\xb0\xc6\x4c\x5c\x84\x71\x2f\xe2\x81\xb4\xc0\xea\x6d\x08\x3e\x56\x7b\xa4\xf7\x30\xc0\xce\x55\xb7\x01\x43\x85\x38\x7e\x62\x2c\x7a\xeb\x58\x67\x47\x6d\xbd\x62\xba\xc6\xc6\x98\x6f\xea\x23\x18\xc9\x50\x46\x0a\x84\xba\x7a\x5d\xb2\xc8\xa2\x30\xd6\xcf\xcc\xa2\x70\xe9\x6b\x4b\xbf\xd6\x25\x3a\xe6\x79\x28\xba\xd6\x2a\xdf\x03\x53\x85\x9c\x91\x3f\x73\x7c\x6d\x01\x3e\xa5\xea\xf1\x9b\xe2\x1f\x2e\xfc\x95\x29\x72\xe2\x6a\xea\x06\x13\xde\x43\x7b\x29\x83\xb1\x19\x71\x2e\x7d\x92\x61\x76\x8f\x91\x3e\x66\xac\xdf\x1d\x11\xf4\xd8\x28\x92\xab\xc5\x8e\x89\xf4\x3f\x91\x04\x83\x6c\x7a\x12\xba\x92\xc8\x35\xab\x63\x51\x40\xc5\x32\x69\xa9\x83\x35\x44\x53\x0d\x41\x31\xcf\x47\xf5\xab\xb5\xaf\x75\x25\xc9\x07\xa2\x73\x44\x65\xf8\xb1\x4a\x4f\xfa\x03\x6b\xa6\xb7\x85\xf7\xfa\x1d\xc6\x50\x6f\x3c\x81\x67\x24\x8f\xbe\xd4\x4f\x27\x51\x28\xc9\xa3\x7f\xa4\x6b\x8f\x2e\x30\x7d\xac\xd9\x63\x26\x2e\xb8\x54\xcc\xa1\xde\x58\xe9\x5b\x14\x6e\xcc\xf3\xa5\x45\xe1\xda\x3c\x2b\x6e\xf1\xa5\xdf\x7e\x39\x1e\xa3\x53\x46\x9f\x0d\x28\x1d\x55\xc0\xf9\x5a\xde\x07\x9e\x73\xc1\xa2\x11\x60\xf3\x73\xd3\xa9\x01\xac\x85\xf7\x12\x0a\x64\xed\xfc\x83\x77\x7e\xc9\xa2\x70\xc6\x48\x31\xd2\xb6\xef\xa9\xc3\xd9\xfe\xb9\x39\x85\x63\xbd\x2a\x91\xc2\x15\xaf\x17\x56\x85\x43\x21\xe6\xb4\xa7\x4a\x10\xd5\x54\x09\x4a\x16\x18\x1d\xe6\x19\x70\x31\x07\x9a\x7d\x88\xd1\x35\x8c\x18\x5a\x49\x8e\x82\x9a\x16\x01\x87\x64\x07\x34\xef\x4f\xe1\x6a\xe5\xe1\xa8\x27\x65\x8c\x0b\x5f\x25\xff\x85\x62\xac\xae\x7c\xed\x33\xd0\xe7\x34\x4f\x1e\xb5\x65\x76\x9c\xb9\x78\xfa\xf7\x7c\x47\x30\x38\xf4\xdb\x9c\xe3\x20\x76\x8e\x08\xe1\xce\x8c\xbc\xf6\x4d\x58\x53\x09\x1f\x25\xa9\x64\x7e\xa1\xd5\x88\xe5\xad\xb8\xe0\x55\x81\x0b\x62\x8a\x61\xcb\x03\x4c\x60\x71\xa9\x04\x13\x74\x4b\x76\x2b\x8c\xdb\xb1\xaf\x77\x4e\xe1\xbe\x49\x92\x86\x9a\xed\x45\x49\x22\xf4\x2c\x0d\x73\x2c\x0a\x2f\xe2\x5e\x28\xf9\x38\xed\xa1\x1b\x78\x27\x0a\x53\xd9\xd3\xb1\xed\xd5\xeb\x12\x00\x27\x0a\xa9\xba\xbd\xcd\x12\x04\xe3\x02\x24\x66\xbd\xe1\x00\x4b\xd7\x3b\x7e\x2f\x88\xf8\x4d\x67\xa9\xe3\xbc\xd9\x77\x25\x68\xc2\xe0\x8f\xaf\x68\x65\xf8\x56\x9d\x84\xcc\x6f\x94\x20\x32\xf2\xb3\x6b\x3f\xc3\xec\x64\x28\x42\xbd\xf4\x75\x34\x14\x5b\x41\x9a\x45\x81\x60\x08\xcd\x27\x68\xc6\x88\x6f\xec\x1f\x4c\x5b\xf6\x7f\xc2\x6f\xec\x64\x6a\x6d\x3e\xf6\x5d\xbf\x52\x65\x46\xc6\xf7\x3b\x06\x1d\xc9\x6f\x24\xbe\x6a\x3f\x73\xfc\x96\xf7\xd2\x88\xa5\x97\x0d\x07\xa1\xd0\x0b\x28\x16\x60\x51\x9f\x58\xdc\x70\x8c\xb4\x00\xe8\x58\x6b\x07\x21\xf9\x94\x2d\x1b\xb6\x97\x3e\xc4\x21\x2a\x9a\x07\x26\xb7\x55\xa0\xf8\x25\xbd\xed\x95\x64\x7a\xf7\x3e\xdf\xdb\x0c\x23\xad\x36\x4f\x2a\x0a\xe3\xeb\xa5\xf9\xbc\x0b\xe3\x6b\x7d\xb0\x09\x26\xa7\x82\x0b\x22\xd0\xa7\x2c\xc7\x66\x5b\x45\x2f\x78\x28\x3a\x05\x44\x0c\xb1\x1b\x9c\xd9\x29\xd3\xf0\xca\xde\xd2\x72\x17\x0d\x23\x85\x15\x76\xd1\x4f\x43\xa3\x8f\x73\x7f\x85\x26\xb4\x48\x5c\x33\x6a\xf7\x05\xd0\x96\xb8\xe5\xf2\xc4\xd5\xe5\xd1\x10\x5e\x65\x12\xf2\xe5\x10\x0b\xab\x88\x40\x30\xce\x70\x23\x0d\x1b\x91\xa5\x5c\xf4\x52\x1e\x71\x4f\xb1\x11\x61\x1c\xca\x90\x45\x45\x69\x6f\x9c\xfc\xe8\xdd\x51\x65\xc6\xdd\xeb\x50\xde\x51\xcb\x6c\x97\x97\x44\x4a\x76\xb3\xfe\xeb\xb1\xeb\x0d\xfc\x02\xff\x4b\x9f\x88\xb5\xdf\x1c\xeb\xb7\xb5\x78\xed\x37\xeb\x37\xdc\x92\xbb\x30\xbc\x46\xec\xef\x18\x39\x24\x5a\xcd\x0b\x53\x9f\x58\x3b\x08\x82\x1d\xf7\xb6\x23\x2f\xc3\xb4\x13\x31\x97\x47\x95\xaf\x58\x6b\x39\x1f\x3b\x07\x4e\xed\x86\x25\x52\x9f\x49\xb9\x97\xc4\x3e\x13\xb7\xcb\x2b\xaa\xfa\x78\x9f\xc8\x0e\x2e\xb8\x39\x0f\xdf\x14\x22\xf5\x7e\xfd\xc2\x68\xcc\x18\x6f\x86\x39\xab\xd1\xc0\xf3\x1c\x0d\xdc\x12\x5f\xa1\x01\x86\xc6\x3f\xd2\xd9\x17\x04\x83\x33\xe1\xf5\xc4\xe8\x4a\x12\xa9\x38\x04\x3c\x5d\x96\xbd\xf0\x33\xb5\x40\x3a\xb5\xe1\x8f\x23\x3d\xd8\x41\xb1\xea\xb3\xcb\x50\xf2\x5e\x3a\x61\x1e\xb7\xc0\x8a\x93\x99\x60\x93\xca\x4c\xa4\x1e\xfd\x02\x50\xed\xd4\x91\xe1\xd8\xed\x6d\x18\xa0\xf7\x24\x30\x38\x22\x89\x0e\x58\x23\x46\x33\xd2\x2d\xaa\x95\x88\xd6\x0c\x21\x3f\x26\x33\x72\xe8\x03\x66\xfb\xcc\x8a\x63\xa2\xcf\xc4\x89\xdf\xae\x93\xc7\x64\xb0\xea\x98\xa4\x09\xa4\xda\x48\xd2\xaf\x5a\xd3\xe8\xd3\xa3\xdd\x90\x62\x93\xc3\x2a\xae\xde\x85\x54\xa7\x30\x89\x7a\x8f\xcd\x80\x8e\x64\x1b\x39\x72\xc9\xb9\x8f\x87\x12\xd3\xf6\x05\x78\x95\x72\x89\xf7\x19\x7b\x98\xa6\x7e\x8e\xea\x86\x8a\x71\xbc\x7b\x83\xcc\x26\xc3\x0a\x0e\xe2\x30\xa6\x9a\xbc\x58\xec\x70\x46\x4e\x7c\x8c\x02\xa5\x68\x1d\x28\xa4\x97\x15\x6a\xc9\xf7\x4c\x41\x93\xde\x51\x0d\x52\x69\x27\x48\xb2\xd8\x47\xdb\x6d\x26\xee\x90\x02\x3f\x06\x46\x0a\x3c\x52\x82\x08\xb1\xbc\x4b\xee\x5d\xe3\xd9\xde\x31\x82\x4d\x3c\xc9\x14\xab\xf7\xde\x30\x2f\xfa\x34\xc0\x3b\xbf\x34\xe0\x34\xec\x20\x14\x8d\xbf\x51\xd4\x08\x9d\x19\x6e\xf1\x76\xa2\x58\x82\x6d\xbf\x5d\x8c\xcd\x49\xb3\x5a\xe9\x98\x4d\x91\x4a\x96\x08\xe8\x7d\x09\x48\x52\x81\xa7\x82\x51\xad\xab\xee\x79\x49\x2c\x45\x12\x15\x3f\xd5\x00\xdc\xe4\xa6\x6c\xbb\xa3\x79\x4a\xdf\xcc\x0c\xcb\x90\xce\x2f\x76\xd0\xcb\xa7\x79\xe4\x97\x09\x11\x29\x85\x57\x4c\xdf\x8f\x48\x88\x33\x6a\xb0\x7f\xf5\xbc\x2c\xf5\xe2\x87\x1e\xea\x96\xee\xae\xeb\xf3\xd4\x13\xe1\x04\x79\x90\xf2\x3c\xc5\x06\xb7\x68\xf0\x7e\xeb\xaf\x76\x75\x6c\x5f\x35\x93\x1b\xa8\xfa\x7d\x55\x05\x49\x59\x85\x71\xe6\x25\x1b\x6c\x90\x2c\xf3\xae\x15\x14\xc5\xbe\x05\x96\x14\x2c\x4e\x27\x4c\xa0\xa6\xd7\xe0\x83\x20\x89\x35\x72\xbe\xe4\x22\x2c\x5f\x7b\x99\x48\x11\x2d\x4f\x92\x30\xd6\x6a\x62\x5d\x60\xf0\x2d\xe2\x8e\x98\x9b\xc5\xcf\x87\xa2\x11\x30\x5e\x14\xe1\x60\xf4\xac\x4f\xfd\x7b\x86\x00\xfe\xa1\x61\xb6\xb0\xf2\xa2\xb0\xeb\x3b\xbf\xf1\x78\xea\x54\xf5\x9a\xbf\xc1\x81\x06\xc4\x50\xd5\xf8\xe4\x3b\xcf\xe0\xab\xef\x0c\x37\xe0\xbb\x82\xe1\x43\xa9\x39\xcc\x1b\x09\x53\x89\x9e\xe5\xf0\xea\x1e\x12\xfc\xb0\x90\xe0\x3f\x36\x9d\x04\x1d\x90\xc9\x98\x34\x7f\x50\x35\x82\x04\xac\x6b\x7e\xbb\x95\xf8\xdc\x02\x0c\xca\x8e\xa7\xd3\x78\xf4\xa5\x85\xfb\x9d\x1f\x54\x5d\xf0\x58\x50\x3a\xc9\xed\xfb\x85\x93\x1c\x13\x3a\xe7\xf2\x1b\xa3\x8a\x19\xb3\x48\x1d\xca\x2f\x7a\x9e\xfa\xe3\x14\xe2\x69\x6b\x60\x2e\xef\x8b\x16\x60\xaf\x74\x08\x9a\x10\xd3\x8a\xb2\x7d\xf0\x9c\x7d\x25\xf4\x42\xe2\x9c\x31\x7d\x10\xa4\x09\x3a\x1c\xfa\x18\x7f\xca\x53\x68\x3b\x74\xbe\xfb\x84\x53\x08\x9c\x0b\xe2\xe1\x92\x99\xec\x20\xfb\x0c\x50\x24\x30\xd9\x58\x2c\xcb\xf6\xfa\xdd\x91\x75\xc9\xd2\x9e\xcf\xe2\x0b\x2e\x2c\x1b\x7f\xa4\x99\xe7\xf1\xb4\xaa\xca\x28\x31\xad\x48\x66\x9d\x38\xe9\x5d\x64\x52\x72\x91\xb6\xb0\xcd\x47\x26\x8b\x89\xa7\xbe\x57\xa3\x36\x5e\x12\x75\xac\x35\x51\x28\x39\xc2\xb8\x37\x0b\x7d\x79\x69\x81\x1c\x59\x1b\x83\xc1\xe4\xc6\xb2\xad\x75\xfc\xdb\xc0\xb8\x37\x7e\x5e\x9d\x59\x1e\xcb\x5e\x2a\x05\x97\xde\x65\x53\x3b\xf5\x55\x44\x22\x3d\x73\xab\xb6\x88\x81\x0e\xfc\xe6\x6c\x9c\x78\x1c\x82\x44\x14\x78\x01\xb7\x11\x65\x74\x8f\xd4\x7c\x65\xd5\x99\xfe\xea\x57\xbc\x8a\x1b\xb7\x27\x4f\x3b\xf6\xc9\xa7\x26\x3b\xd9\x03\xc7\xc9\xf2\x46\x1f\x99\xaa\xf7\x22\x76\x0e\x09\x83\xb0\xe2\xa5\x67\x8c\x38\xba\x23\xe9\xda\x33\x72\xea\xc3\x03\x64\xad\xfb\xac\xa0\x34\xd2\x9d\x53\x90\x1e\x69\x49\x04\xfc\xc9\xa7\x23\xd5\xfb\x90\xda\x58\x33\xf6\xc8\x07\xd6\x80\x06\x2b\x8b\xd4\x73\x65\x5c\x2e\xd4\x32\xaf\x36\x11\xe1\x98\x89\x5b\x4b\x9d\x74\x12\x50\x48\x1a\x98\x30\xc5\xe7\xc9\x51\x7d\x27\xbc\x24\xea\xb1\x4c\x26\x9d\xda\xd7\x14\xf1\x58\x6f\xda\xbe\xc6\xad\x1b\xdf\xc5\x3d\x6e\x33\xf2\x86\x19\xec\xd5\x28\x3a\xb8\x3c\x8a\xb4\x40\xd4\x4b\x96\x44\x08\xe3\xe9\x52\x99\x49\xc9\xdb\xc0\x8c\xbc\x29\xfb\x52\xf0\xa1\x18\xef\x05\xee\xbb\x5c\x8c\x2d\xa4\x2c\x1d\x03\x54\xd0\xe1\xfd\x8b\xbe\xd5\xcc\xfe\x22\x01\x40\x06\x75\x6c\x60\xdb\x65\x29\x47\x0c\x8d\xb8\xf8\x03\x23\xbb\x3e\x2d\xfb\xde\xf5\xcb\xd1\x99\x4c\x14\x62\x7a\x4f\xd5\xa8\x9c\x36\x98\x77\xe6\x4a\x1f\x4a\x47\x45\x28\x39\x6b\x49\xa7\xa9\x86\xec\x8b\x64\xe2\x27\x33\x7d\xf8\xb5\x06\x12\x91\x92\x98\x62\x5c\x80\xca\x20\x85\x21\x1c\x7c\xba\x8a\xc5\x28\xd9\x88\xe0\x49\xc7\x0f\xdd\xce\xd8\x5d\xef\x8c\x45\xa3\x80\xee\x71\x4d\xc4\x56\xb2\x11\x47\xea\xcb\x8a\x45\x90\x0d\x60\x3e\xa9\x00\x9a\xda\x23\x9c\x40\x41\xd8\xb3\xe9\x3d\x49\x1c\x9b\x3a\xcf\xc0\x9b\x3a\x9b\x03\x48\xa6\x8a\x68\x85\x53\x67\xe3\x19\x04\xd3\x7b\xe6\xff\xce\x8d\x83\x8a\x04\xe0\x17\x3a\x45\x67\x81\x45\x76\x32\x22\x69\x35\x0d\xb8\x3b\x5d\x4a\x03\x9e\x53\x0d\xf6\x15\xef\xde\xdd\x6b\x54\x94\xba\x11\x32\xaf\x9e\xd4\xf6\xa7\xfb\xe8\x9d\x30\x0e\x40\xd3\x06\xc4\x4a\xad\x64\x34\x98\xe6\x6a\x9b\xf7\x12\x63\xcb\x66\x68\xdf\x2b\x46\x4c\x61\x1f\xbd\xc3\x52\xdf\x50\x8f\x03\xd8\xc9\xfe\x4a\x8f\x1c\x7b\x6b\x22\x2d\x77\xe0\xe7\x7a\xfe\xc2\x16\xdc\x2c\xdb\x70\xb3\x37\x2d\x56\x35\xf5\x48\x58\x60\xe2\x70\xe1\x7d\x52\xbc\x4f\xca\xf7\x4a\x10\x1a\x07\xc0\x0c\x36\x17\x53\xc4\xe6\x19\x6a\x29\xf3\xd5\xc8\x9b\xb1\x69\x05\xb1\xcb\xbc\x07\xd7\x2b\x10\xfb\x77\x9f\x30\x74\xea\x28\x91\xbb\xf1\xd8\xd5\xcb\x9b\x4d\x35\x72\x67\x15\xe4\xce\x56\x23\x77\x36\xa5\x23\xf5\x85\x21\xb5\x99\x41\xee\xa1\x87\x0a\xa7\x00\xbf\xab\xb8\x15\x64\x0e\xbd\x2c\xb5\xc0\xe5\x6a\x4f\x29\x44\x1e\x09\xb0\xd1\xbf\x90\x0c\x08\xc4\x02\x31\x6d\x26\x05\x73\x0a\x69\x3b\xd7\x63\xe0\xd7\x93\x90\x39\x0f\x50\xd4\x96\x10\xf7\xbd\x5d\xaa\x04\xef\x57\x41\x6e\xfa\xc9\x94\x94\xac\x98\x97\x6c\x05\xeb\x82\xe1\xaa\x1a\x44\x5c\x74\x08\xe2\x53\xb0\x5e\xc7\xa8\xf6\xd1\x5c\xbf\x96\xcc\xd0\xaa\x46\x40\xe6\x55\x3d\xcb\xc4\xa8\x14\x9a\x25\xfc\x5d\x4e\xc8\x6f\xe7\x84\x58\x03\x27\x54\xe7\x7f\xdc\x29\x8a\xc2\x80\xcb\x50\x51\xc2\x02\x57\x32\xc4\xfd\x29\xd1\x3b\x25\x1e\x76\xae\xf9\x6d\x27\x48\x44\x31\xe9\x5c\xdf\x60\xd4\xee\xff\xa2\xee\xfe\x29\x3a\x17\x7a\x8b\xba\xe6\xf2\x9b\x95\xb7\x86\xbd\x20\xdc\x21\x99\x13\x53\x85\xf1\x62\x27\x53\xf8\xaf\xba\xca\x8a\xcf\xf0\x92\xf1\x24\xe2\x92\xf7\xc6\x3c\xce\x3a\xd6\x1a\x21\x59\x9f\xad\xff\xfa\x95\xf5\xdd\x2d\xfa\xf0\xa1\x3a\x7a\x56\x7a\x99\xcc\x14\xad\xa3\x14\x3c\x8f\x30\x3c\x37\x14\x12\xfd\x38\xa4\x0d\x4c\x49\x41\x01\x55\xaf\xa5\x3a\x44\x4e\x15\x8e\xd3\x7a\xc1\x9c\x2e\x23\xf3\x30\xa7\x10\x4d\x9d\x9f\x5d\xfb\xc9\x1c\xfc\x3b\x88\x6f\x23\x91\x2d\x25\x43\xbb\xa9\x7c\x95\xb4\x77\xc6\xc8\xd4\x23\xa2\xef\x1d\x2f\xe9\x83\xe2\x9c\x4c\x57\x2e\x0b\xa7\x26\x31\x55\xb7\x81\x10\x6a\xa4\x1f\x2b\xb4\x5f\x26\x3a\x6e\x4f\x4a\x29\xef\x48\x6d\x1a\xf7\xbd\xe3\x79\x21\xe4\x7d\x94\x3a\xae\x80\x58\x54\x15\x2f\x4b\xd2\x8a\x55\x54\x5b\xab\x01\x4c\x80\x25\x99\xbb\x17\xfb\xfc\x06\x93\xf6\x0c\x69\xbe\x16\x95\x8b\x04\xc1\x23\xa6\x17\xb0\x45\xf8\x5d\xdc\x62\xb5\x64\x53\x73\xad\x8a\x8a\x0d\xd1\xdb\x5c\xb1\xc4\x25\x88\x1e\x19\x1b\x3c\xbb\x63\xad\x69\x53\x2f\xb4\xc2\x11\x15\x2c\x38\x9e\xb6\x1b\x0d\xb9\x6f\x7f\xfd\x12\x7d\x77\x6b\xa4\x00\x5b\x3a\x82\x2a\xc4\x88\x79\xb7\x76\x51\xed\xa8\x69\x38\x1a\x3b\x5e\xff\x25\x42\x2e\x0d\x21\xf7\x0a\xb2\x2d\xef\xdf\x5e\xea\xb6\xab\xb6\x02\x57\xa8\xb3\x7c\xde\xf0\x64\xe1\xa9\xea\x96\xa7\xaa\xab\x4f\xd5\x3f\xb1\x4b\x25\x67\x50\x4f\xcc\xaa\xd8\x00\x8e\xf4\x2d\x9a\x22\x31\xbc\xf4\x96\x98\x82\xaa\x99\xe8\x94\x8e\xc6\x1e\xf1\xa8\x6d\xd8\x01\xf5\x8b\xe9\x5f\xc9\x94\x8e\xa6\x9e\x96\xb5\x39\xb4\xc5\x54\xd4\x30\x9c\x51\x4a\xed\x63\x77\x5e\x5c\xc5\x97\xe0\x62\xdc\xe9\x2d\xb0\xdc\x28\xf1\xae\x4b\xf5\xad\xc1\xf7\xc3\xc1\xe0\xff\x29\x95\x52\x2d\x28\xa6\xb3\xf0\xab\x27\xc2\x8b\x4b\x59\xa2\x1d\x7f\x8a\x9a\x65\x8d\x6f\xec\x19\xe9\x4e\xd1\x52\xdf\xfd\x41\xcb\xfb\x73\x60\xe0\xcd\x29\x5c\xae\xa0\xc1\xbb\x3a\x24\xf8\x73\x7d\xd9\x7e\xae\x6f\xdb\x6f\xb5\xb7\xed\x09\xa0\x0f\xd1\x6b\x1d\x8e\x6e\x1b\x2f\x2c\xbc\x64\xb5\x72\xd9\x63\xc2\xef\x54\xc9\x6f\xbd\xb0\x77\xc9\x99\x5f\x65\xe6\xbb\x55\x00\xeb\x28\x20\x93\xcc\x4d\x3b\x95\xba\xf8\x22\x6f\x70\x43\xde\xfa\x30\x00\x4f\xa3\x90\x13\x86\xe9\x17\xcd\x49\xdc\x31\xf6\x8a\x8a\x4c\x60\xbd\x61\x63\x3d\xd1\x67\x17\x23\x0b\x2d\x6b\x3b\x44\x73\x04\xd4\xb2\xf5\x8b\x5c\xdc\xcb\xfc\x85\xfc\x8e\x33\x32\x9e\x6a\x3d\x32\xa3\x68\x85\xe9\x43\x2e\x30\xfa\x16\x88\xfe\x09\x1c\xb1\xfc\x7d\x79\xb7\x06\xa2\x7f\x0c\x9f\x59\x4e\xb9\x96\x96\xc2\x00\x87\x9e\x98\x37\x2a\xbf\x2a\xf3\xaf\xa6\x53\xd4\x5f\xb3\x0b\xdc\xe3\xbc\x58\xe4\xc5\xf1\x14\x7e\x7a\x5f\xec\x07\x03\x84\xc6\xea\x67\x76\xda\xd8\xb7\x5c\x66\x2e\xaf\x44\x96\x4c\x52\x36\x34\x01\xd1\x37\x1b\x43\x25\x00\x3d\x88\xe7\x86\x22\xc6\xa3\x55\x77\xfb\x1b\x55\x81\x7a\x2b\x89\x22\x36\x49\x79\x87\x45\x91\xd1\x85\x5b\xf4\x9b\xbd\xe2\xae\x7e\xa1\xb9\x36\x68\x5c\x6c\x9c\x4f\xd0\xf3\xe1\x96\x7c\xf6\x21\x81\x50\xf1\x49\xd2\xa0\xd9\x8b\x29\x2a\xe0\x2e\x87\x16\x85\xc9\x74\xc1\x06\xea\x62\x5a\xda\x40\xc5\x89\xcc\x95\xf2\x79\x8f\xba\x21\xe2\x93\x54\xdb\x52\x4c\x51\x79\x77\x29\xc7\xd1\x4e\xa2\x28\xea\xcd\x3d\xa5\xd9\xbb\x94\xe2\x82\xf9\x61\xf2\x4f\x69\xc4\x05\x22\xbc\x18\x31\x9d\xfc\x4f\x6a\xc1\xe7\x14\xae\xa7\xc6\x48\xf6\xe5\xd4\x04\x73\x3c\xc6\x87\xe1\x60\x0e\xaf\xf1\xe9\xd9\x1c\xae\xf0\x61\x73\x0e\x5b\xd3\x56\x17\xdb\x8a\x7c\x3c\xf8\xc3\xc1\xd8\xde\x3a\xae\xb7\x12\x55\xf2\xcb\x14\x49\x32\x8d\xcd\x3c\x27\x86\xc4\x11\x10\x3a\x12\x02\x87\x83\xeb\x98\xbb\xab\x8c\x42\xea\x98\xf0\xbd\x02\xd3\xfb\xbe\x88\x1d\x0f\x84\x93\x80\x74\x42\xe0\x4e\x00\x99\xe3\x02\x73\x52\x25\x4c\xef\x4d\x57\x7a\x5d\x75\x02\xb2\x35\x45\x77\x8c\x37\x12\xb3\xf5\xa0\xf3\xf8\x0e\xdc\x92\x0f\x29\x06\x03\xd4\xa1\x0b\x0f\xa7\x6d\x26\x70\x26\x53\x59\x2d\xe5\xe4\x70\x73\x73\x40\xe9\x52\x52\xaa\x9a\xef\xfd\x66\x3d\xdd\x57\x2d\xe0\xc2\x93\x9a\x27\xe1\xa0\x9e\xe4\xab\x6e\x4e\xb7\x8e\x79\x36\xda\x50\xff\x25\x46\x22\xe7\xce\x94\xec\x4d\x61\x38\x04\x8c\x64\x2b\x81\x64\xce\x8d\x22\x7f\x87\x53\x13\x87\xb7\x88\xd1\xfb\xb4\xa7\xbd\xc3\x46\x99\x3d\x44\x75\xf2\x53\x3b\xeb\x0d\x69\x1e\xae\x17\x32\xa7\x8c\xdf\xab\x60\xd3\x21\x71\xb5\x2b\xad\x51\x28\x02\xfe\x9a\xbe\x9e\x3a\x8e\x13\x8f\x06\x76\x8c\x7d\xe2\x93\xe9\x33\xa3\xb0\x30\xb4\xb8\xaa\x45\x90\x8b\xc3\xce\x40\x52\xb4\xb6\x3c\x22\xf9\x1e\x9d\xb4\x32\x5c\x18\xcb\xe3\x8f\xa7\x23\x61\xcf\xc8\xc9\x54\x31\x93\x2e\x26\x97\x83\x19\x79\x9f\x80\xd0\xa7\x32\xd5\xef\x8c\x8a\xed\x33\xc2\xf3\xc6\x1c\x8e\xa6\x77\xda\x7e\xfe\xfa\x65\x3c\xd1\x8c\x9b\xc8\x42\x4c\xd4\x39\x85\x9d\x85\x2e\x24\xa6\xde\x31\x36\x01\x17\xe4\xda\x53\x9b\x72\xed\xa9\x43\x30\xb2\xf0\xc2\x7b\x9c\xc4\xf2\x52\xc9\x29\x90\xb5\x5f\x83\x14\xb1\x76\xe3\x22\xfc\xab\xa0\x2b\x43\x10\x3f\x88\xfb\xdd\x87\x0f\x87\x68\x17\x9e\xa1\xe9\x06\xa7\x23\x61\x5b\xd6\x5c\xf3\x8b\x38\xe0\x10\xac\x0e\x57\x58\x12\x75\x49\xf8\xea\x3b\x58\x9d\x71\x92\xa5\x3c\x41\xa7\x13\x54\x09\x61\xc1\x2d\x58\x1d\x23\x06\x43\xdc\x1c\xba\x8c\xdd\x62\xa7\x6d\x61\xcb\x2c\xab\xb8\x8a\x75\xd1\xbe\xea\x90\x98\xb1\xe1\xe8\x14\x4d\xc6\x48\x77\xd8\x5e\xf4\xd9\xaf\x5f\xeb\x18\x82\xd6\x2d\xdb\x9b\x87\x8e\xcb\xe5\x8c\xf3\xd8\x9a\x13\x9a\xb3\xd0\x87\x04\x33\x1a\x28\x1a\x7d\x34\x85\xd6\xac\x66\x21\xa0\x8b\x77\x39\xd8\x46\xcd\x95\xcf\x24\xef\xb8\xcc\xbb\xb6\xd6\x08\xeb\x33\xf5\x8f\xbb\x16\xd3\x46\xa1\x51\x55\x0d\x44\x12\x4b\x6b\x2d\x59\x23\xe1\x1a\xf1\xd6\x4c\x8c\xb5\xd4\x07\xab\x5c\x4b\x70\xd1\x97\x3b\x4f\x37\xac\x08\xf0\xe7\x69\x89\x83\xaf\x14\x28\x1d\x60\x14\x71\x4e\x2b\x92\xc5\xfb\x95\x64\x69\x81\x43\xdb\xc9\xaf\xef\x77\xa6\x79\x06\x2e\xd3\xc9\xbb\x69\xab\x3f\xe6\x39\x4a\x04\x18\x8a\x4a\xfd\x3c\x99\x82\x84\x1d\xda\x76\x53\x74\x95\xa5\x32\x0c\x6e\x8b\x1b\x9a\xba\xe2\xb6\x62\x91\xc5\xf9\x75\x85\x13\xc4\x91\xbd\xf4\xe0\xcc\xc4\xa9\xf6\xa6\xa3\x3f\xad\xe3\x4c\x09\x08\x07\x28\x26\x9c\x64\x4a\x22\x38\x53\x4c\x95\x75\x72\x99\x59\x60\xed\x88\xd0\x02\xeb\x98\x49\xeb\x9b\xfd\xe7\x3d\x6a\xa1\xf3\x83\x36\x46\xad\x6f\x10\x8e\x97\x85\xb1\xb9\x28\x2d\x37\x26\x93\xb8\x2f\x57\x53\x5a\xb1\x7e\x78\x5f\x5f\xbe\x33\xc4\x0f\x83\x39\x6c\x4f\x4d\x68\xcb\xb7\x9a\x9f\x70\x55\x7f\xa7\xfa\x79\x62\x51\xf8\xd1\xbe\x59\x3f\xbb\xf6\x93\x6a\xce\x68\x8c\xd8\xb1\xb2\xfa\xe3\x7a\xf5\x03\xfd\xa1\x54\x8a\x24\xbe\xb0\xe8\x8a\x2c\xd3\x4b\xd1\x3d\x4c\xa2\xb2\xb8\xdf\x1d\x9d\x26\xb6\xcb\xa9\x76\x6f\x83\x19\x09\x79\x91\xda\xaf\xdd\x7a\x21\x4f\x46\x54\xc9\x43\x44\x2c\xaf\x88\x70\xe7\x25\xf1\x94\x0b\xd9\x49\xa5\x08\x71\x64\x9f\xa6\xfa\x92\xf6\xa3\xe1\x67\x67\x1c\x98\xa0\x14\xbe\x4e\xdb\x1c\x43\xeb\x80\x26\xc3\x31\x9f\x84\xde\x75\x15\xb8\x0e\xa6\x79\x8d\x34\x73\xaf\xb8\x27\xab\x86\x31\x23\xeb\x75\xec\x5b\xb6\x75\x9c\xab\xea\x16\xa1\xe0\x32\xc9\x44\x93\xd2\x33\x9b\xf4\xb4\x11\xba\xb9\x96\x28\x20\x5a\x9d\xcf\x5b\xf2\x43\x1d\x87\x01\x0c\xdb\xaf\x9c\x58\x7c\x11\xf1\x9e\xd1\x70\xef\x98\xef\xee\x98\x2b\x7e\x05\x68\x6e\x94\x09\x4b\x2f\xf4\x8c\xec\x62\x7f\x6a\x81\x28\x32\x79\x15\x3c\x1a\x06\x44\xe6\xd8\x54\xf4\xd9\x55\x35\xa2\xa7\x35\x40\x63\xa2\x3c\x41\x81\x76\x55\xc0\x6a\x3f\xee\xac\x46\x28\x85\xd7\x1e\x59\xd7\x5c\xe7\x34\xe4\xb3\xfa\x54\x73\xae\xb1\x72\x17\xa4\x84\xd2\x7b\xac\x4b\xef\xce\x85\x51\x3d\x95\x4b\xb3\x24\x24\x25\xd1\xf2\x17\x4a\xc5\x8b\xbd\xbc\x8f\x4a\x12\x91\xfc\xef\xee\xe4\xf0\x5f\xbc\x93\xc3\xbf\xbf\x93\xdf\xef\xb7\x93\xdf\x57\xee\xe4\xdf\xdf\xbb\xe1\x3f\xbd\x77\xea\x84\xb6\x40\x93\xde\x3e\x12\xb7\xa3\x27\xed\x2f\xd9\xa6\x7e\x51\xe8\xc6\xb2\xec\x19\x99\x24\xf0\x0c\x04\xb2\x3d\x73\x83\xa4\xf0\xf2\x59\x71\x5c\x57\xea\x9f\x50\x49\xcd\xf8\xf3\x87\xfa\xe7\xb6\xa0\x9c\xc8\x6a\xc4\x73\x0a\xdf\xa7\x4d\x81\xe2\x8d\x03\x50\x79\xb7\xdf\x60\x52\x38\xee\xb8\x17\xbd\x80\xf9\xdc\x5f\x36\x31\x5c\x47\x5b\xe3\x16\x93\x4c\xc9\x6f\xe4\x2a\x7b\xcc\xc5\xf2\x46\x63\x4c\x5d\x65\xf1\xc6\xf5\x45\xbc\x18\x61\x3a\xf9\x9b\x43\x3e\xab\x1a\xdf\x96\xf3\x6e\xbc\x12\x10\x25\x23\xf2\x6a\xda\x9a\xa6\xb5\xcd\x6c\x58\xc7\x16\x72\x74\x6c\x21\x8c\xd1\xe9\xa2\x1d\xe7\x11\x21\xf2\x0e\x5b\xf4\xdc\x9a\x0f\xcd\xca\x65\xdf\x5d\xe6\xd3\x56\xdb\x95\xff\x3d\xab\xf1\x8a\x8d\xb8\x30\x36\xe2\xc2\xd8\x88\xbf\xf4\x91\x29\x28\x6c\xbf\xd1\x49\xa0\x66\xfb\xad\x64\x00\x6d\x9b\xbc\xe8\x69\x71\x7f\xdb\x64\xd1\x6e\x9b\xfc\x7d\x8a\x8e\x1a\x3c\xdf\x8f\x8f\xd3\xf6\xe3\x55\x31\xa4\x64\x03\xfd\xb9\xf2\x4b\xaf\xa6\x4a\x08\xd1\x66\x88\x1f\xa6\xf7\xf1\xf6\x5a\x4a\x9d\xb2\xb4\x88\x66\xe1\x64\xdf\x1d\xfd\x39\x23\xa7\xd3\x9c\x2b\x3d\xa8\x68\x65\x5e\xe6\xa1\x47\xf5\x7d\x92\xdd\x41\xb7\xbb\x7d\x81\x69\x43\x0a\x04\xf3\x71\x8a\x0e\x16\xa8\x46\x6a\xee\xe7\x7d\x52\x46\x31\xad\xdc\x74\x99\x73\x5f\x4b\x13\x8c\xeb\x58\x93\xc4\x2b\x9e\x69\xad\xb3\xd2\x06\x9e\xf8\x6f\x6f\xc6\x44\x8c\x7c\xcd\xa2\x19\xae\x62\xc9\xf6\xa7\xed\x11\xfa\x1a\xfc\xe5\xaa\xc3\x19\x94\x21\x83\x32\x1f\xb6\x3c\x98\x91\x0f\x7a\xee\xf5\xbc\x38\xc6\x6f\x6e\x29\x51\x96\xaf\x46\xf0\x66\xea\x58\x63\xd9\x7b\x6c\xc1\x97\x65\x4b\x82\xe5\x89\x1d\x91\x37\x53\x30\xfe\x26\x23\xab\xb3\x70\xdf\x6a\xd1\x9a\x0d\xe8\xed\xb4\xd9\x8a\xaa\xc2\x90\x15\xbb\x72\x60\x52\xf6\x75\x34\xcd\xc6\x0d\xc7\xcd\x29\x37\x2b\x37\xf1\x4e\x2b\x86\x38\x5a\x13\xfb\x3d\xab\xe8\x3a\x87\x88\xea\x61\x91\xa0\x6a\x51\xb0\x0c\x7f\xae\x17\xb2\xa0\xb1\x4d\x5b\x58\x35\x25\xe8\x05\x9c\xfb\x28\xd0\xd5\xb4\x5e\x73\x62\x8e\x53\xdc\x35\xac\xbd\xe8\x3a\x2b\xd5\xaa\xe6\x42\x1a\xf1\xe8\x99\x5b\xe1\x56\x3e\x08\x4d\x0f\x5f\x96\x30\x09\xb2\x7b\x9f\x43\xaa\xf0\x53\xc7\x5a\x7b\x93\x8b\x83\xa2\x5b\x73\xd8\x40\x96\x00\xfd\xa8\xb9\x65\x5b\xa7\x98\x8f\xb1\xd1\x88\x67\x1c\xf5\xd6\x3b\xcb\x17\xf9\x0a\xe5\x77\x97\x66\x1e\x2f\x32\x0e\x0b\x6d\x0d\x50\x60\x53\xb1\x70\x17\x86\xea\xd3\x82\x2a\x70\x5c\xb6\xe7\x73\xc8\xba\x46\x87\xc2\xba\x77\x24\xfe\x60\x7d\xe6\xe7\xf1\xdb\xbc\x4a\xec\xed\x26\x39\x5c\x9b\x0a\x69\xfe\x22\x89\xb2\xb1\x4e\x4b\x60\xac\xd6\x2b\xf6\x01\x1d\x6b\x4d\x56\x81\x77\x19\x6d\x88\x0a\x0f\xa3\x5e\x7d\xf1\x95\x50\xff\x19\x95\xac\xfa\x6e\x29\x5b\xb6\x40\xe9\x2c\xc0\x50\xb1\xf5\x39\x4b\xb4\x74\x90\xef\x3b\xf2\x7f\xcf\x68\x2b\x03\xcb\x51\x85\xf6\x53\xf1\x9a\x0f\xc8\xdd\xab\xab\xa1\xe0\x3f\xb2\xb8\x39\xc0\x2d\xdf\x99\xdd\x75\x8e\x93\x1c\x1a\xe7\x14\xbc\xee\x1d\xda\x92\x8a\x88\x59\x39\x70\x01\x61\x5d\xd8\xf1\xc1\x48\x8f\xa0\x04\x93\x5e\x74\xd1\xdb\x44\xcb\xc6\x27\x26\x36\xcb\xb9\x07\x33\x8f\xc2\xcc\x23\x59\x97\x42\x4c\xa1\x68\xb6\x6d\x92\x66\x94\x2d\x37\x16\x5a\xee\x2d\xb4\x94\x95\x96\xaf\xd1\xf2\xbb\xf1\x73\x87\x0b\x8d\x44\xc3\xa2\xe8\x8d\x32\x8d\x87\xa6\xf1\xd2\x4e\xa9\x63\xfb\xff\xfd\xbf\xd6\x92\x8b\xce\xc2\x5e\xd4\xd1\x9c\xc1\x1d\x1d\x7d\x2f\xde\x5b\x30\x3c\x98\x79\x84\x77\xdb\x85\x07\x8f\x45\x5c\x71\x9d\x0b\xa2\xc3\x37\x7a\x97\x7f\x44\x22\xe0\xd1\xff\x90\x24\xfe\xa5\xc6\xf5\x12\x6b\x74\xe9\xa3\xb0\x2f\x79\x2a\x49\xec\xc4\x74\x64\xf9\x4c\xb2\x9e\xb5\x16\xdb\x31\x3c\xfa\x9f\x7f\xa4\xbf\x93\x2b\x36\x65\xfa\x42\xc3\xfe\xa5\x0a\x6d\xc5\xc4\xfe\xe3\xd1\xa5\x1c\x47\x45\x53\xe1\x08\xb4\x2e\xd2\x19\xbf\x14\x72\x67\x02\x74\x57\x17\x82\x8d\xc7\xe7\xdc\x0f\x31\x3c\x45\x1e\x8e\x09\xc2\x6e\x9b\x9f\x6e\xee\xa0\x2b\xfe\x11\xff\xfa\x87\xf8\xf5\x8f\x58\xfb\xe9\x06\x5d\xed\x8d\xc9\x6f\x24\x13\x9c\x59\x14\xdc\xee\xca\x6c\x4e\x98\x2b\x7f\x03\x86\x8f\x61\x5f\x90\xb0\xab\x73\x83\xe2\x4d\x7e\xf6\xef\x41\x8e\x62\xf5\xf9\x8d\xcb\xf3\x1b\x74\xcd\x01\xce\xf2\x03\x2c\xf1\x00\xf3\x7b\x63\x47\x38\xf1\x08\x53\x4b\xfd\x2f\x40\x93\xff\x96\x71\x37\x0d\xf1\x5f\x8d\x30\xff\x03\x0b\x5e\x90\xe8\x85\xc9\xfc\x6d\xd4\x99\x76\x1b\x9d\x5f\x74\x54\x55\xde\x67\x9b\x80\x59\xc8\xce\xc1\x53\x7f\xba\x80\xee\x8f\xef\x20\x54\xbf\xf6\x30\x37\x19\xdb\xc2\x88\x51\xdd\xd1\x21\xb1\xde\xf3\x59\x9e\x5a\x40\xa1\xb3\xe3\x04\x53\xa9\x51\xfb\x90\x58\xaf\xfd\x50\x96\x65\x3f\x38\x31\x61\xe8\xaa\xd1\xbe\x5a\x6e\x76\x73\x01\xeb\x96\x78\x5d\xc8\xfa\xee\x21\x64\x7d\x76\x06\x59\x3f\x55\xf3\xfe\x32\x05\x0f\x58\x05\xb9\x16\x91\x67\xde\x4c\x35\x4a\x9d\x14\x28\xf5\xe5\x14\x93\x5e\x9e\x52\x98\x12\xb7\x0b\xd6\x56\x9e\xb5\x3a\xaf\x7a\x51\x54\xbd\xd6\x55\x8f\x17\x96\xb6\x20\x1d\xb7\x64\x7f\x0a\x1c\x12\x1d\xe6\x48\x76\x51\x4a\x54\x63\xbc\x52\x44\x4f\xa3\xbd\xa8\xeb\x48\x01\x7e\xd7\xe1\x02\xa6\x8d\xc8\xe5\x4b\x4c\x42\x81\x6a\x0e\x13\xc3\xa1\xdb\xbd\xa7\xc5\xf2\xb8\xb5\xa2\xfb\x0c\xc5\xc8\x97\x82\x77\x6e\x93\xac\x93\x66\xe6\x61\xc6\x62\xd9\x91\x49\x47\x27\x1d\x5f\x60\xc9\x47\x16\x05\xb6\x61\xaf\xb6\x0a\x3d\x63\xe4\x80\x93\x19\xe9\xea\xb9\x56\x8d\xf9\xb6\x92\x38\x08\xc5\x58\xd3\x1a\x37\xb1\x0f\x38\x79\x99\x50\xf0\x36\x6d\xeb\xb5\xfe\x5a\xbe\xef\x98\x96\x65\x05\x73\xdc\xa4\x97\x30\x96\x85\x29\x8f\x02\xa3\x6d\x2a\x6d\xfc\xcd\xb1\x5a\x43\xcb\xef\x3d\xdf\x04\xa8\x43\x9b\x81\xd6\xaf\xa0\x2f\xc1\x1a\xb1\x1e\x9a\xf0\x5a\xda\x0d\x5a\x0b\xc6\x13\x8d\xd2\x2f\x1f\x2b\x29\x7c\xc5\x38\xff\x77\xfa\xb8\x2f\x07\x75\x32\x79\x11\x96\xe9\xc9\x65\x17\x99\x90\xd4\x02\xd1\x67\x67\x75\xd1\x53\x97\x23\x57\x84\x35\xdc\xc3\x25\x31\xd4\x74\x61\x32\xd8\xeb\x5e\x30\x26\x14\xaa\x48\x5c\x25\xd7\xfe\x25\xc7\xf0\xc5\xc0\xec\xb2\x02\x5d\x9f\x8c\xc6\x93\x52\x38\xf2\x88\xa0\x8d\xf1\xcb\x17\xe6\xb9\x5a\x0f\xb0\x4a\xcc\x33\x88\x7c\x31\x26\xc5\x01\x27\x9f\x3d\x12\x2f\x80\xbc\x9e\xb8\xb5\x40\x44\xfe\x95\xfd\x6f\xf3\x88\x6b\x85\xb7\x5a\x55\xb1\xa4\x86\x2d\xf5\x3a\xef\x3d\xb5\x41\x57\x94\xc2\x3b\x8f\xc4\x23\xbc\x9b\x1e\x77\x41\xc0\x83\x21\xa5\xf6\xb5\x2c\xd4\xa2\x72\x4e\xe1\xb6\xdb\x10\x1b\xcf\xac\xa1\xac\xa9\x7e\x78\x25\x7c\x1f\x06\x91\x30\xe1\x3a\xdb\x6c\xe7\xd8\xcd\x5c\x1b\x93\xae\xb4\x12\x75\x4f\xe6\xc6\x3a\x14\x2f\x3c\x29\x45\x67\xfa\x69\x77\xd9\x3d\xb9\x9c\x62\x43\x47\x87\x6a\xcb\x15\x90\xcd\xba\x79\x4c\x00\xf5\x82\xa2\xc5\xee\x1c\xc3\xb4\x18\x9f\xdd\x1c\xaa\x72\xd3\xa0\x65\x2d\x8b\x6c\xd5\xb2\xdc\x74\xab\x99\x39\xae\x57\x48\x19\x68\x96\x26\xf3\x98\x9f\x67\x1e\x1c\xf0\xba\x2e\x43\x14\x97\x03\x95\x98\x88\xd2\x27\x3b\x8c\x6c\x7b\xa8\x0d\x5b\x30\xe1\x71\x99\x7f\xc1\x3b\xf8\x6f\x6f\x12\x46\x51\x32\x33\x3f\xcc\x48\x0d\x1a\x40\x3c\x29\x93\xc9\x82\xcf\x95\xbe\x58\x8e\x0d\x0b\x3e\x6f\xf9\xdc\x37\xbc\x5b\x98\x53\x78\xd9\x5d\x52\x21\x85\x01\xd1\x29\x1f\x2a\xca\xf2\x16\x8b\xbe\x02\x71\x99\x7b\xd4\x6b\x05\x7c\x03\xb5\x78\xcb\xca\xeb\x7b\x75\xd1\x18\x89\x02\x7b\x8d\xfb\xde\x25\x28\x18\x2a\xee\x05\x8e\xff\x37\xd3\xc1\x4f\x78\xf5\x8f\x17\xba\x7d\xd7\x9b\xb7\x52\xc4\xd7\x5d\x63\x58\x75\xa5\xc9\x8f\x6b\x51\xd8\xba\x97\x0a\xa9\xc2\x87\x8a\x64\xd6\xe4\xcc\xad\xa4\xc3\x75\x94\x11\xb1\xee\x42\x9c\x85\x19\xb9\xea\x36\xf1\xa6\x0b\x37\x75\xbd\xe1\xe0\x6e\xdf\x2d\x51\xc8\x7a\x7b\xcd\xfc\xa4\x68\x0d\xb4\xf0\xa9\x88\x75\x6f\xe2\xad\x7c\xd0\xf7\xf0\xf4\x0e\xa6\xb0\x74\xec\x83\x5a\x6c\x85\xc2\x46\xf5\x08\x99\xea\xff\x34\xb9\xf8\xc4\xc9\xeb\xee\xbf\x8b\x56\x2c\x75\xbe\x48\x28\x64\xb9\x89\x5b\x5d\xb0\xf6\xb6\x2d\x13\x3f\xcc\x2b\xde\x69\xaa\xde\x61\x12\x8b\xf6\xb0\xf4\x90\x16\xc5\x8a\x29\x58\x28\x64\x67\x65\xa1\x56\x41\xfa\x8b\x8d\x3f\x95\xe5\x5a\x57\xe9\x77\xdc\x5b\xf3\x5d\x76\x5a\x96\xe5\xac\xb6\x2e\x38\xae\x0e\x48\x72\x7c\xad\xf0\x92\xd9\x99\xa2\x34\x57\x30\x5b\xb0\x68\xec\xb2\x97\xc0\x8e\x67\x6e\x47\x28\x48\x9d\x48\x06\x84\x22\x82\x5c\x13\xc1\xe3\x2e\x48\x78\x30\x28\x88\xe0\x9c\xc2\xa1\x61\xef\xd6\x2d\x0a\xe7\xfa\xd9\x4b\x7c\x05\x42\x27\xfa\xd7\x44\xed\x13\x7c\x36\xd5\x8c\x1d\x0b\x1c\xe9\xdf\x31\x9b\x5a\x14\x76\xba\xce\xcf\x1b\xbb\xcc\x16\x00\xee\xd8\x36\x3a\x6f\x6b\x0e\xef\x75\xa9\x7e\x6b\xcd\xe1\x5d\x5e\xbb\x08\xc7\x8b\x25\xc7\xf9\xaf\x39\x9c\x15\x35\x8a\x54\x43\x58\x23\xff\x35\x87\xed\xa2\x86\x49\x82\x82\xe5\xfa\x79\x0e\x6f\xbb\xed\x91\xbf\x1a\x41\x7f\x29\xcb\xff\x4e\xb7\x06\xf2\xef\xbb\x39\x91\x34\xec\x80\x31\x51\x5c\xb4\x4c\x3c\xeb\xd6\x92\x64\x6e\x77\x6b\x39\x1c\xde\x77\xeb\xf0\xfe\xae\x3b\x9f\xeb\x6b\xa8\x91\xd5\x29\x1d\x53\xe7\x14\x4e\xef\xe4\xb6\x17\x02\x30\xac\xcd\xc8\x5b\x83\x80\x97\xfd\x88\x2b\x81\x0f\xb6\x19\x11\xfd\x1b\x0c\x39\x63\x1c\x63\x6a\x6e\x32\x1a\x30\x7e\x20\xa1\xdf\xe9\xc2\x59\x17\xb6\xbb\xf0\xae\x0b\x6a\xc5\xf3\x50\x77\x13\x91\x8c\xb9\xbc\xe4\x59\xda\x0f\x93\x47\x7e\xe2\xa5\x7a\xf3\xc3\xf8\x42\x3f\x8c\x59\xcc\x2e\xb8\x78\xa4\xb7\x66\x97\x47\x13\x6b\xfe\x8d\xc2\xee\x6a\x1c\xbe\x60\x64\x6f\x64\x09\xe6\xfb\xe8\xbf\x66\x6d\xa2\xe7\x58\xee\xa6\x62\xa2\xf1\x88\xe5\x5b\x5a\x38\xf0\x48\xdc\xf7\x3e\xd5\xf1\xb6\x31\x7c\xea\x4c\x2a\x62\xc5\xae\x57\xb5\xf9\x3d\xe8\x3a\x89\x20\x96\xc0\x48\x23\x9f\xba\xed\xe9\xcc\x5f\x79\x60\xe1\x72\xaa\x3e\x30\x86\x13\x1c\x74\x89\x95\xca\xdb\x88\xa7\x97\x9c\xcb\xc2\xba\x2a\x4a\x98\x8f\x96\x55\x82\x30\x0c\xa1\x5c\x18\xc4\x71\x21\x12\x61\x8a\xbe\x70\x62\xed\xb0\x30\xe2\xbe\xa2\xc3\xaa\x4d\x67\xeb\xf8\xb8\x13\x88\x64\xac\x93\x02\x51\xe3\xca\xa8\xa3\x7a\x9e\xc5\xe4\xa7\xf7\xca\xde\x02\xef\xd0\x3e\x64\xe0\x7d\xb0\x1b\x19\xcb\xee\x48\x91\x11\x4d\x6c\xd9\xdc\x56\x3f\x36\x81\xd9\xb7\xe4\x43\x04\xd6\x7f\x59\x40\x62\x9d\x8b\x8c\x3d\x06\xfd\x6e\x64\x29\x7e\xe2\x08\x7d\xfb\x3e\x46\x8a\xad\x48\xe1\x48\x91\x86\xd9\xa8\x0c\x72\x68\x97\x91\x0f\xe3\xbe\xeb\x2a\xfe\xb2\xcf\x30\x68\xfe\x1c\xbc\x75\x7b\x2a\xc9\x2b\x41\xc1\x7b\x6a\x9f\x47\xe0\x3d\xb7\x9b\x42\xad\x3e\xb3\xcf\xc8\x9f\x1f\xf5\xd2\x23\x07\xf0\xb2\x02\x32\xd6\x7c\x3e\xa7\x2f\x78\xe2\xfc\x3c\x60\x61\x6c\xff\x0c\xe3\x50\xda\xaf\x04\x79\x17\x52\x32\x50\x1f\x89\xfb\xaf\xa3\xf1\x28\xef\xb7\x63\xcc\xa7\x82\x44\x10\xe4\xd1\x3b\x61\xdc\x91\x14\xff\x88\x11\x06\x73\xb2\x1c\x87\x8f\x2e\xc9\x13\x6a\xc7\x44\xfc\xc9\xbf\x81\xfc\x93\x7f\xa3\xb6\x7a\x74\xd4\xe3\x9c\x60\x97\xc0\x13\x6a\xe3\x93\xc3\x93\x39\x51\x6c\x10\x7d\xf1\xff\x07\x00\x00\xff\xff\xa8\x51\x24\xdf\x82\xae\x01\x00"), + compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\xdc\xbd\x0b\x7b\xdb\xb8\xae\x28\xfa\x57\x1c\xed\x6c\x2f\x72\x0c\xab\x76\x5e\x6d\xe5\x70\xf9\xa6\xef\xf7\x23\x49\x3b\x99\x66\x72\x72\x28\x99\x76\xd4\xd8\x94\x4b\x51\x71\xd2\xd8\xfb\x6f\xdc\x1f\x74\xff\xd8\xfd\x08\xea\xed\xc7\x74\xf6\x5e\xfb\x9c\x73\xef\x5a\xf3\xa5\xb2\x04\x82\x20\x09\x82\x00\x08\x82\x5b\xc3\x44\x06\x3a\x8c\x24\x91\xf4\xde\x49\x62\xd1\x88\xb5\x0a\x03\xed\xf4\xb2\x0f\x0d\x45\x24\x28\xd0\xf4\x5e\x09\x9d\x28\xd9\xd0\x2e\x67\x12\xb4\x3b\x64\x0a\xf4\x22\x07\x1b\x93\x02\x44\x91\x1d\xd0\x90\xa3\x56\xf9\x87\x72\x6d\x19\x3a\xa2\x40\xd2\xc5\x82\x16\xa8\x06\x44\x94\x50\xed\x82\x28\x50\xe9\x65\x54\x1b\xb1\x0b\xa2\xc1\xe2\x2f\x57\xa0\x49\x52\xaa\x60\x0f\x92\xa2\x02\xb1\x8c\xed\xef\xd6\x99\x10\x01\x79\xad\xe5\x6a\x03\xc2\x4b\xd5\xee\x03\x2f\xaa\x4d\x96\x11\xfe\x0b\x28\xe1\x24\x81\x32\x2d\x65\x62\x04\x09\x4a\xc4\x1c\x40\x50\x10\xc3\x97\x71\xfe\xf7\xd0\x17\x10\x0e\x35\x0a\xcb\x24\x26\x24\x2a\x91\xf8\x10\xa2\x82\xc4\x60\x19\xed\xff\x32\xaa\x23\x12\xc0\x32\xdd\x65\xc2\x39\x09\x4b\x84\x3f\x82\xb0\x20\x3c\x5a\xc6\xfc\xbf\xb3\x2d\x21\x89\x60\x65\x6b\xca\xcd\x89\xc8\xb0\xd4\x9c\xc7\x30\x2c\x9a\x13\x2e\x23\xff\x3f\xac\x85\x43\x12\xc2\xba\x36\x96\x1b\x39\xab\x89\xb9\x1d\xc6\x98\x74\x79\x5f\xba\x43\x62\xde\x7b\xa6\x1e\xa2\x4b\x25\xee\x6c\x09\x28\x88\xdc\xad\x96\x01\x91\x97\x22\xa2\x54\xf0\x36\x2b\x08\x45\x93\xf7\xea\x45\x21\x29\x17\x26\x49\xa9\xfc\x4d\x51\x1e\x8a\x7e\xdc\x5f\xc6\x00\xbc\x86\x83\xf0\x12\x9a\x61\x19\x0d\x14\x63\x74\xb0\x0a\x11\x04\xcb\xa8\x48\x50\xc2\xe6\x57\xb1\x41\xc1\x06\x0f\x57\xe3\x83\x68\x25\x46\x12\x95\x90\xc6\x75\xa4\x50\x30\xdc\xa3\x75\x68\x21\x5c\x87\x98\x84\x74\x71\xc3\x55\x23\x64\x03\x52\xb0\x8a\x1d\xf6\x61\xa4\x88\xf9\x26\xd8\x91\x52\xfc\x8e\x48\x0a\x09\xeb\xf4\x92\x43\xd9\x4b\x5a\x2d\x2a\xce\x93\x0b\xa6\x89\x6a\x25\xb4\x97\xad\x2d\x0b\x0a\xdb\x6c\x5c\xc1\x54\xe0\xd1\x05\x1e\xc1\x3a\x3d\x71\x28\x9b\x4d\xe5\xfa\x3d\xd1\x6a\x51\x7d\x2e\x2e\x98\x72\x39\x28\x66\x5e\xe5\x0b\xeb\x58\xc8\x91\xbe\x62\x02\x2e\xcd\xb2\x45\x17\x14\x26\x8c\xd4\x2b\xc8\x26\xe2\xb9\xbc\x58\x50\xd8\xd4\x90\x0c\x21\x24\x29\x2d\x82\x02\x67\x9d\x1e\x3f\x14\x3d\xde\x6a\xd1\xe4\x9c\x5f\x30\x7d\xce\x2f\x32\x0a\x92\x73\x79\xc1\x14\x24\x0b\x0a\xeb\x9b\xa5\x32\xac\x59\x4f\xe9\x56\x37\xeb\x2b\x5d\xf4\x95\x3a\x4f\x72\xbc\xe2\x5c\x5f\x30\x09\xe2\xd7\xe9\x35\xc8\x04\x22\x53\xcc\xcc\x4c\x7d\x9e\x5c\x80\xca\xbb\x5e\xfd\x22\xa6\x76\xb7\xd7\x39\x64\xa2\x27\xda\xed\x1c\x91\xa8\x21\xa2\xbd\xbf\xd3\xd6\x15\x2d\x95\xc4\xb4\xb5\xc2\x16\xff\xe5\x51\x41\x69\xd4\xe2\x60\x46\x27\xc7\x9c\xac\xc4\x9c\x73\x4f\x3c\x0e\x03\x81\x2d\xf8\x0b\x0a\x54\x41\x81\x6c\x0b\xe0\x19\x1d\x2d\x92\xe4\xd4\x1d\x26\xfd\xec\xd1\x4b\x28\x85\x80\x75\x7a\xc1\xa1\xe8\x05\xad\x16\xe5\xe7\x81\x19\xdf\xe0\xa2\x67\x70\xda\x2f\x49\xf6\xa5\x25\x0c\x4f\x05\xf9\xd8\xf3\x15\xcc\x54\x1a\xc5\x35\x9f\x82\x48\xc6\xd1\x58\xb8\xe3\x68\x44\x64\xcb\xf1\x1a\x4e\xeb\x8a\x50\x0a\x6a\x41\x0b\xcd\xf4\x8a\x64\xf0\xce\x61\x28\xb5\x50\x92\x8f\xe3\x7f\x3a\x85\xf8\x98\x9a\x75\x40\x5f\xa9\x68\xd6\x78\xae\x54\xa4\x88\x73\xa5\xf5\x34\xf6\x1e\x3c\x18\x85\xfa\x2a\xf1\xdd\x20\x9a\x3c\x10\xe3\xc9\x83\x20\x52\xe2\x81\x3f\x8e\xfc\x07\x5d\xb7\xe3\x76\x1e\x5c\x85\x52\xc7\x0f\x9c\x96\x6c\x39\xee\x64\xe0\x94\x24\xd2\xa8\xc6\x22\x20\xd8\xf9\x05\x24\xec\x1a\xbb\xb9\x03\x82\xf6\x92\x66\x93\x68\x26\xdc\x69\x34\x25\x94\xf6\xcc\x37\xed\x72\xd0\xae\x8f\xdf\x4b\xc3\x99\x63\xbd\x2e\x96\x92\x70\x48\xba\x9d\xce\xa1\xa6\x19\x3b\xb9\xd3\x24\xbe\x22\x97\x58\x2f\x85\xad\x4e\x2f\x1c\x12\xc9\x18\x53\x29\x84\x7d\xe3\x44\xfe\x77\x11\x68\x67\x8b\xe9\xbb\xa9\x88\x86\x0d\x39\x9f\xcb\x64\x3c\x36\x42\x32\x7f\xca\x8a\x38\x59\xc5\x0e\xcb\xc1\x9b\xcd\x29\xd9\xa7\xb0\xd5\xed\x65\x6d\x4b\x1a\xa1\x6c\x48\x77\xfb\xb0\xd3\x6c\x12\xc9\x7c\x6d\x64\x99\x32\xff\x1a\x42\x24\x0d\x87\x64\xeb\x9a\x48\x9c\x99\xe6\x8f\x6e\x75\x4d\xf3\x52\xaa\xba\xbd\x8c\x3c\x14\xb9\x47\x6c\x4c\x46\x14\x4e\xd8\xea\x01\xdf\x1a\xa5\x8c\x5b\x8c\xee\x69\xc6\xb8\x2b\x5b\x97\x75\x0f\xf6\x44\xbf\xe3\xc9\x43\xd5\x6f\x77\xbd\xae\xe9\x8b\x2d\xe9\x6e\xa7\xdf\x89\x66\xa7\x44\x1a\x49\xeb\x72\x4a\xe7\xf3\xf4\xb7\x0f\xca\xf5\x29\xed\x6b\xcf\xfc\x0a\x40\xb9\x01\xc5\x76\xf7\xa4\xeb\xa3\x9c\x6e\x36\xb7\xaa\x65\x7b\x92\x61\x39\x23\xb1\xf3\x21\xd4\xf3\xb9\xc1\xd6\xef\x7a\xca\xf5\x4d\xfd\x1d\xbb\xc0\x3c\x5f\xd3\x4c\xdb\x28\x7a\xd8\x59\x50\xf8\xb6\x56\xb4\xa7\x40\xdd\xf5\xd3\xa3\x73\x78\x9a\x4d\xf4\xb5\x10\x2c\x03\xa1\xf0\x7d\x99\x9c\xf4\x6b\x2e\x07\x0f\x3b\xfd\x1b\xed\xa9\xfe\x40\x7b\x63\xbd\xa0\xf0\x94\x75\x8a\xa1\xb8\x2c\xa3\xbe\xe7\x9e\x04\xdf\x53\x8b\x82\x7d\xdf\x54\x65\x51\x06\x01\x81\xa7\x4b\x50\xef\x2c\x96\x6c\xda\xdc\x2f\xb0\xc7\x35\x72\x19\xb5\x4b\xc4\xb9\xbe\x28\x5e\x2a\xfb\x52\x99\x97\xb9\x6c\x35\xa5\x3f\xb0\x31\x79\x55\xe2\x94\x57\x16\xb1\xe1\x13\x63\xbd\xca\x51\x89\xad\x73\x3e\x69\xa9\x94\x35\xfc\xec\x95\xea\x59\x21\xff\xda\x0e\x72\x3a\xc2\xbd\x92\xa4\x36\xdc\x60\xdf\x52\xc1\x84\xeb\x17\xa0\xd9\xf8\x23\x3d\x67\xec\x7e\xdb\xeb\x2c\x0a\x82\x5e\x57\xfa\x6b\xdb\xeb\x42\xde\x67\x06\xfe\x23\x1b\x93\xd7\x25\xfa\x8f\x8d\x98\xca\xaa\x55\xec\x0c\x34\x93\xa9\xec\xed\xe9\x76\xbb\x47\x95\xa9\xf8\x5c\x57\x17\xae\xbc\xf8\xd7\x6a\xf1\xf3\x8b\x12\xd9\xca\x4a\x0f\xe9\xf2\x52\x49\x03\xf7\x73\xa3\x0a\x74\x7e\xd1\xc3\x39\xa0\x8d\x76\x62\x38\x1e\x34\xd3\xa6\x17\x2c\x3a\x5c\x9d\x50\xa4\xf1\x42\x9c\x1d\x1b\x1d\x97\xc2\x33\x46\x74\x0d\xb3\x11\x6b\xb9\x50\x29\xe3\x6e\x36\x45\xb5\x02\xc0\x6e\xa6\x89\xad\xe6\xae\xa8\x06\x44\xb5\xaa\xc4\x54\x15\x2c\xd5\x63\x14\xea\xac\x26\xbe\x54\x53\xb3\x99\xac\xaa\x0e\x12\x96\xb8\x3e\xe5\xb6\xd2\xdb\x6a\xa5\x90\x54\x2b\xe6\xa6\x62\xb1\xa2\x62\xa3\x89\x67\x55\x07\xab\xab\x6e\x36\xf9\xfa\xfa\x81\x33\xee\xfa\x34\xb0\x54\xdc\x2c\x53\x01\xbc\x4a\x49\x50\x9b\xfd\x1a\x0a\xa3\xe7\x98\x18\xa6\x70\xe3\x48\xe9\x75\x22\x06\xa5\x39\x8a\xf2\x05\xfe\x07\x2f\x2b\xf2\xe8\x17\xb1\xb1\x99\x81\x2c\xf3\x25\x63\x6c\xac\xfb\x1d\xcf\x3c\xdc\x68\x94\xc9\x58\xc1\x3a\x41\x25\x5b\x46\x07\x83\x17\x6b\xa5\xa1\x6c\x6f\xd0\x13\xe4\x6f\x58\xfa\xf3\xfa\xd2\x0f\x36\x95\x7e\xa0\xe6\x1d\xfc\xfc\x9e\xeb\x2b\x77\x1a\xcd\xd6\xeb\x2a\xff\x2e\x57\xe1\xf9\x77\x26\xb3\x96\x77\xcc\x52\xdb\x9f\x92\x6e\x97\x7a\x9d\x43\xd5\x6c\xca\xc3\xce\x7c\xae\xcc\xea\xd9\x39\x94\x7d\xd5\x92\x5e\xaa\x6d\x62\x65\x5c\x73\xb9\x43\x51\x04\xbd\x67\xf8\x26\x10\xe1\x18\xbe\xd8\xe7\xe1\x38\x8a\x14\x3c\xb1\x3f\x54\x94\xc8\x01\xfc\xb0\x3f\xc6\xd1\xa8\xb7\xae\x39\xcd\xe6\xa6\xc6\xce\xe7\x9b\xbe\x6e\x31\x66\x94\x2b\x43\xcf\x27\xb6\x69\xac\x7a\x7f\xeb\xe3\xaf\xe9\xd2\x76\x55\xe0\x4c\xb9\xc1\x15\x57\x4f\xa3\x81\x38\xd2\x24\xa1\x3d\x7e\xb8\xbf\xbf\xf3\xf8\x60\x3e\xdf\x3f\xd8\xed\x3e\x3e\xe4\x7d\x52\xd6\xb8\xc1\xa8\xe0\x5e\xf9\x55\x4b\x9d\x27\xad\x2e\x7e\x61\x3b\x74\x91\xab\x50\xdf\xa3\x50\x12\xc7\xa1\x1b\x0d\x9b\xf3\x0b\xa8\xe8\xc6\xd6\x06\xc9\x49\x33\x2a\x4e\xb0\x44\x61\xd2\x6a\x41\x50\xa5\x32\x98\xcf\x09\x6f\xd9\x02\x86\x42\x90\x84\x53\x23\x0a\x70\x66\xf3\x9c\x2c\x5d\x22\xab\xf7\xb7\xec\xa2\x8c\x26\x6d\x69\xd2\xbf\x4c\x93\xce\x69\xb2\xd6\x90\x59\xcb\x16\x85\x36\x8e\xa3\xff\x96\xfd\x0a\x2d\xc6\xa4\x4a\xe9\x48\x18\x1a\x55\xbc\x4a\x87\xa0\x3d\x5b\x47\xc2\xf8\x3f\xd9\xfe\xc1\xee\x4e\xa7\xd9\xdc\x7f\xb8\xbb\xb7\xfb\x4f\xc6\xfb\xfa\xbc\xdd\x16\x17\xad\xc4\x4b\xaa\x14\xc0\xef\xeb\x78\x4f\xb9\xf1\x74\x1c\x1a\xa9\xb5\xa0\xf0\xc7\x7a\x28\xec\x53\x04\x92\x92\xfd\xa2\xb5\xf4\x0b\x5c\x6b\x17\xe2\xfb\xd4\x80\x32\x6b\x71\x52\xe5\x05\x4d\x51\x31\x27\x82\x25\xf5\xe6\x26\x7d\x75\xde\x6e\xeb\x8b\x96\xf0\x0a\xfd\xb8\xb3\xc8\x14\xe5\xb4\xdf\x95\x64\xff\x32\x32\xb6\x7e\x9d\x8e\xee\x22\x27\x88\x82\x96\xeb\xf4\xf3\xad\xff\x50\x6e\x28\x07\xe2\xf6\xe3\xd0\xf6\xae\x58\x07\x6a\x04\x61\x0d\x36\x59\x0b\x9b\xe9\x39\x87\x79\x0b\x8d\xf6\x3d\xe6\xb1\x7e\x9d\x23\x60\xf9\xb7\x76\x06\xbe\xa0\xc0\x97\x71\xda\xae\xca\x55\xa7\x70\x48\xf4\x61\x37\xd3\xf6\xce\x4a\x8a\x5d\x07\x50\x0d\x69\x77\x0f\x89\x28\xd3\x8a\xd6\x59\xa6\x7d\x08\x0a\xa2\xc5\x74\x55\xe7\xc0\x91\x0a\xd6\x35\xc7\xa8\x7a\x1d\x18\x64\xba\xde\x3a\x51\x69\xc0\xba\x20\x0a\xb0\xc2\xd3\xba\x04\xb7\x0b\x43\x4f\xc2\x28\x53\x1d\x87\x9b\xaa\xde\x43\xa5\xfb\xca\x93\x8b\x94\x50\x7f\x6d\xbf\xe3\xcf\x73\x75\x61\x46\x27\xde\x30\x4f\x52\x38\xd0\x08\x39\x96\xab\x95\xbb\x3a\x30\x88\x8b\xf5\xfa\xd9\x32\x30\x24\x17\x9b\xb4\xaa\x55\x05\x80\x63\x91\x64\x65\x91\x92\x2f\xb3\x56\x08\x02\x2c\xc6\xd7\x14\x2b\x39\x2d\x97\x0a\x42\x84\x45\xa3\xb5\x45\x4b\xae\xc9\x15\x85\x21\xbc\x58\xb5\xfa\x68\x75\x97\x15\xba\x31\xaf\xde\x9c\x7c\xfc\xe0\x4e\xb9\x8a\x05\x6a\x66\x01\xd7\xc1\x55\xc9\x99\x3d\xd1\x64\x46\xae\x34\x38\xa7\x57\x61\xdc\x08\xe3\x86\x8c\x74\xe3\x86\x8f\xc3\x41\xc3\x94\xdc\x6a\x38\x2d\xe9\x4e\x44\x1c\xf3\x91\x00\x83\xc0\x28\x47\x03\xc3\x05\x37\xb2\xc4\x66\x37\x69\xed\xf1\x2c\x44\xfc\xee\x36\xbd\x0f\x78\x2c\x1a\xbb\x5e\xea\x20\xf0\xa3\x68\x2c\x78\xc9\x3f\xa0\xfa\x33\xa3\x2c\x7a\x57\x92\x38\xbc\xf1\xe4\xe3\xc7\x77\x8e\xd1\xfa\xb0\xd4\x4e\x56\x4a\x26\x13\x5f\xa8\xc2\x4a\x57\x7d\x04\x97\x8d\xd7\x1f\x4e\x0d\xb8\x47\xd4\x21\x6b\xef\x74\xf7\x1e\xee\x3d\xda\x3d\xd8\x7b\x38\x9f\x17\xcf\x87\x4c\xcd\xe7\xa4\x33\x57\xd4\x68\x22\xb4\xd9\x24\x5b\x61\xfc\x22\x94\xa1\x36\x5d\x31\x9f\xab\x7f\xef\xd2\x3a\x3a\x24\xc9\xd2\xb0\x57\xa3\x61\x0d\xe1\x2f\xde\x7d\x3c\x3a\x2d\x28\x3f\xc8\x4a\xd5\xed\xc6\xac\x94\x6a\x84\x32\xd6\x5c\x06\xe6\xe5\x09\x02\xe1\x97\x96\xe3\x64\x28\x4f\x4e\x8f\x5f\x7f\x78\x59\xe0\x7c\xec\x65\xb2\x2d\x75\xba\x98\x02\xd2\x0d\x2c\xbc\x79\x59\xc0\xee\x67\xb0\xa5\x96\x3c\xcc\xde\xa1\x96\xe4\x86\xb1\xd5\x96\x14\xed\x6f\x4b\xeb\xba\x80\xe3\xac\xee\x77\xaf\x4f\x4a\xad\x79\xf4\xd7\x25\x27\x32\x2d\x2a\x1b\x47\xc7\xc7\x47\x7f\x14\x85\xbb\x1d\x2f\x93\x9f\x83\x95\x0e\x25\x55\xb8\x91\xe6\xf3\xad\xcc\x44\xcf\xc4\x6b\x8a\xf4\xe3\x93\x37\xcf\x9f\x9e\x36\x66\xa1\xbe\x6a\xf0\xc6\x30\x14\xe3\x41\x43\xf2\x89\x18\x34\xfe\xa7\xd3\xd2\x2d\xe7\x7f\x62\x85\x56\x0a\xdf\xa4\x44\x9d\xeb\xc2\xc5\x19\x0a\x22\x68\x5f\x78\xc8\xe8\x53\x6d\x66\x10\x5a\x3d\x96\xc4\xae\x67\xc8\x13\xb8\xc2\xd5\xdb\x58\x23\xa4\x68\x5d\x38\x24\x2a\x5f\x65\x74\x05\xac\xf1\xee\xe3\x87\x97\xcf\x8f\x1b\x1c\x71\x35\x3e\x08\x31\x68\xe0\x62\xd0\x40\x62\x1b\x7e\xa2\x1b\x91\x1c\xdf\x35\x62\x21\x1a\x4e\x2b\x43\xd3\x72\x1a\x42\x6a\x15\x8a\x18\x2b\xf8\x85\x96\x8c\xea\x2d\xd9\xf1\xfe\xb2\x8b\xff\xa2\x81\xb6\xa7\xf3\xee\x4c\x80\x33\xbb\xc4\x25\x76\x60\xb0\xd9\x57\x3c\xfe\x38\x93\x9f\x54\x34\x15\x4a\xdf\x91\x84\xd2\xfb\x12\xb5\xc9\x85\x55\x16\x90\x54\x5a\x16\x31\x53\x0d\x49\x4a\x2f\x67\xaf\xc9\x25\xb1\xbf\xa0\x50\x5e\x67\x9a\xbc\xd6\xa4\x68\xd0\xae\x57\x18\xbf\xd2\x1d\x42\xc4\xa4\x3b\x82\x90\x75\x7a\xe1\x61\x94\xaf\xc8\xad\x56\x4a\x40\x74\x1e\x5e\xa4\x83\x53\xad\x5e\xf4\x02\x16\x10\x53\x59\xa9\xa6\x20\xab\x65\xcf\x2b\xc8\xaf\xf5\x34\xbe\xbe\xc2\x92\x46\x34\x88\xb4\xc4\x7e\x4e\xd7\x90\x9d\x81\x6f\xa8\xea\xf9\xae\xdf\xf3\x99\xef\xfa\x29\x31\xbe\xf5\xe9\x84\x43\x52\x23\x65\xc8\x5e\x1b\x84\x30\xcc\x89\x99\x68\x72\x87\x2d\x1f\xd2\xbc\xe9\x5e\x4d\x38\x5b\x17\x51\xfa\xb5\x53\x9a\xe1\xd2\xb4\xaa\xf0\xdb\x6c\x6f\x76\xcd\xaf\xdc\x1c\xb8\xb7\x3d\x6c\x05\x38\xee\x0d\xa4\x3d\x18\x54\x07\x70\xa4\xcd\xb2\x83\x03\x88\xfb\x09\x81\xcb\x4b\xfd\x69\xac\x84\x92\x4f\x7b\x52\xde\x42\x9d\x91\x48\x40\x4e\xc6\x8a\x0d\x55\xbb\xf1\x54\x94\xbe\xaa\x6a\x16\xf9\x12\xf5\xfc\x76\x2a\x02\x1d\xca\x91\x59\x94\x70\x31\x2a\xfc\xf2\x32\xf7\xd8\x2d\x7b\xb2\xa5\xbb\x6d\x56\x80\xdc\x85\xbb\xd5\xed\x2d\xad\x53\x1d\xaf\xda\xf5\xd2\xe5\x06\x8f\xcb\x7b\xe9\x32\x96\xae\x4b\xe9\xd2\x90\xca\xfa\x8a\xc8\xdd\xea\xd4\xc5\xb5\x1b\x20\x8e\x20\x13\xc3\xa9\x4c\xcd\x26\x6c\x0a\x36\x95\xb9\xff\x38\x17\x9c\x39\x86\x01\x62\x18\x34\x9b\xcb\x50\x25\x5a\x05\x42\x89\x55\x50\xbb\x05\xd4\x10\xa1\x86\xcd\xe6\xc8\x40\x8d\x40\xb9\xa3\x62\x1a\xe4\x50\x57\x08\x75\xb5\x0a\x57\xbe\xb8\x94\x10\x94\xd8\x6f\xb4\x5e\x6b\xde\x2a\x54\xee\x62\x10\x4a\xea\x73\x4f\x1c\x6a\xdc\xc8\x34\xcc\x67\x2a\xc6\x4d\xb5\x73\x71\xb1\xce\xfb\x3f\x5b\xab\x88\xa2\xc2\x63\x57\xdf\x70\x78\x47\x14\x18\x01\x08\x92\xb6\x1c\xa7\xac\x18\xdf\x95\x39\x50\x22\xce\xdb\x4d\xe6\x9d\xdd\xc8\xd4\xa9\x1e\x7c\x2d\x99\x41\x5b\xa0\x3b\x2a\xa1\xbb\xdf\xf6\x3a\xc0\x8d\xd2\x9c\x7f\x3e\xa9\x7e\xee\xd6\x3e\x9f\x56\x3f\xef\x80\xef\x49\x08\x3c\x53\x85\xd5\xd2\x9f\x6f\xd0\xd2\x77\x11\x7a\x80\x8a\x3f\x7c\xdb\x00\xb8\x57\x02\xc4\x56\x7c\x97\x65\x9f\xfc\x53\x24\x42\xa2\xeb\x19\x84\xf7\x5d\xb6\x5a\xa9\xa9\x80\x3d\x78\xe5\x9d\x5f\x2c\x32\x09\x79\x66\x60\x41\x16\x2d\xb8\x2c\xcf\xf8\x53\x49\xca\xd3\x5c\x92\x23\x49\x9e\x1a\x00\x4a\xcb\xf3\xfc\x4d\x4a\xa0\x74\xaf\xac\x81\xa4\x28\x20\x62\x6c\xf2\xbb\x4a\x4b\xca\x63\x51\x43\xff\xc6\x7e\x05\x5b\x0d\x56\x61\x9b\xf7\x41\xb2\xad\x2e\xbc\x92\xc6\x32\xcb\x2b\xc5\x0a\x8c\x9c\x78\x25\x53\x4f\x36\x85\xad\x0f\xa9\xbf\xdb\x94\xe8\xf4\x24\x7b\x25\xdd\xf8\x2a\x1c\x6a\x42\x7b\x74\xab\x1c\x15\x82\x3b\x3a\xca\x1d\xa6\x16\xb3\x34\xf3\xc9\xdd\x36\x2c\xde\xb1\xfb\x62\x5d\xf3\x4f\x0e\x37\x32\xb6\xe7\x08\xc5\x8f\xec\x51\xe5\x8e\x98\xf9\x19\xa2\x88\x35\x93\xc7\x36\xc8\x20\xc4\x0f\x3e\x31\xe8\xcc\x72\x93\x41\x2e\xc4\x38\x16\x86\x5a\x0c\x1e\xc9\xf7\x19\xdc\xa1\x1b\x60\xd5\x7e\xa5\x27\x0c\x1e\x69\xba\x10\x5d\x10\xe1\x90\xec\x5b\x6a\x52\xf2\x94\x7b\x55\x9d\x83\x69\xc5\x43\xac\xf8\x2a\x6b\x32\xc5\x4a\x1b\x86\x06\xc3\x5d\xe8\x84\xec\x78\x5d\x63\x0a\x1a\x50\x08\x3d\xe5\x8e\x16\x90\x95\x1d\x2c\x16\x0b\x22\x69\x0f\x7b\x7b\xb1\xd8\x60\xcd\xbd\x36\x03\x25\x40\xba\xc1\x33\xf3\xe7\xb1\xf9\xb3\x57\x2c\x08\xcb\x31\x37\xf4\x7e\xb1\xa8\xec\xe0\xbd\xae\x19\x72\x76\xed\x9a\x91\x81\x04\x09\xaa\xaf\xdc\xe1\x98\x8f\x62\xef\x26\x0a\x07\x8d\x0e\xed\xe1\x2a\x36\x9f\x4f\x49\xea\x16\x8d\xd8\xfd\x02\x42\x46\x02\xa6\x09\x2e\x65\x66\x25\x66\x9c\xf8\x10\x9a\x45\x71\x85\xed\x0f\x02\xa5\x94\x30\x1a\xd0\x47\x99\x79\xa7\x3e\x1a\xf1\xd4\x4b\x5c\xde\x6c\x12\xa2\x99\x9e\xcf\xef\x17\xf4\x5c\x5c\xb0\xc4\xe5\x04\xcd\x24\x30\x10\x2b\x10\x0a\x76\x3f\x42\x8b\xda\x92\xb8\x80\x84\x49\x37\x00\x6e\x74\x64\x30\x7a\x8e\x40\x3d\x67\x98\x6f\x4f\xb9\x57\xec\xa9\x24\x33\xf2\x5c\xe6\x1d\xd5\x28\x87\x2c\xe1\x17\x09\xf7\xdb\xde\x3e\xf8\x5e\x99\x19\xec\xde\x8d\x74\x79\xc5\x9d\xec\x6e\xf7\xef\x08\x07\x81\xc2\xcd\x0b\x9a\xcd\xa8\x7f\x8b\x31\x7d\xca\x0d\x41\xb9\xdf\xcd\xdb\x3b\x7c\x11\xf4\x95\x6b\x86\xda\xbc\x32\xc3\x00\xd2\xf5\x29\x5d\x90\xb2\x7f\x4d\x2f\x48\x04\x7e\x69\x80\x7c\xdb\x54\x33\x26\x02\xa4\xe9\xd6\x21\x09\x8d\xae\x00\x8a\xc2\x4b\x49\x22\x08\x5c\x1f\x12\x12\xd2\x1c\x47\xf5\x2d\xf0\xfe\xfd\x34\x52\x3a\xf6\xf8\xc2\xbb\x4f\x77\xb7\x24\xbb\x5f\xe0\x00\x1e\xff\xaa\x4c\x50\xee\x88\xd4\x45\xc2\x9a\xf5\x62\x46\xde\x49\x90\xee\x15\xa4\x62\x5b\x55\x59\xee\xeb\xe6\x68\x30\x14\xe6\xd7\x9e\x82\xb1\x11\xe8\x85\x6c\xfb\x59\x97\xe8\x13\xf3\xdd\xb4\xe1\xd9\x46\x51\x2e\x3d\x09\x51\xcd\x87\xf3\x32\x5f\x8c\x90\x85\x20\xc9\x76\x3a\x91\x2d\x5f\x48\xb2\xd5\x01\x05\x09\x2e\x74\x14\xcc\xef\x2e\xe8\xfc\xb7\xa4\x6f\xd2\xf5\xf4\x7e\xdb\x73\x86\xb7\x0e\x70\x2f\x39\x17\x17\xf3\xf9\x7d\xe8\x9d\xc1\x77\xef\xac\x12\xb5\xf6\xa2\x34\x6f\x53\x2d\x49\xe5\x5a\x52\xd7\xb3\x13\x40\xb9\xd7\xc0\x19\xe1\x2c\x81\x88\x09\x98\x11\xd9\xff\x28\xcf\xf9\x85\x2b\x3c\xfb\xef\xb0\xa2\xe7\x15\x5b\x89\x51\x4f\xe1\x76\xd5\x0f\x6a\x44\xe7\xd4\xc8\x8d\x7c\x09\x36\x3a\x62\xb1\x1d\x65\x26\x08\xd1\xe7\xc9\x85\xa9\x86\x43\xc2\x48\x82\xce\x66\x5a\xa2\x1b\x64\x3f\x71\x43\xf6\x9a\x70\x48\xdc\x90\x7a\x89\xfb\x3d\xfd\xf1\x9d\x42\x42\x73\x67\x42\x61\x48\x28\x77\xd2\x0b\x5c\xdf\x98\x04\xae\x4f\xb1\xad\x86\x39\x4d\x6b\xd3\x8a\x7b\x15\xb7\x05\x92\x91\xf6\x89\x1b\x81\x86\xfb\xa9\xa7\x5c\x09\x3f\x3c\xb1\xb0\xcb\x14\x87\xa8\xe8\xbc\xcf\xd8\xdc\x8f\xf2\x5c\x5e\x34\x9b\x53\xb2\x5b\xea\xd7\xf7\x55\xae\x43\x48\x40\x48\x76\x2f\xbc\x2f\x12\x94\xa7\x80\x7b\x4f\xe4\x02\xbe\xe6\x6b\xe0\x97\xb5\x5a\x4e\x25\x6c\xe5\x49\x3e\xe1\x35\x04\xec\xfc\x02\x22\x86\x98\x5d\x65\xa4\x9d\x66\x1d\xa8\x4d\x0f\x3b\x18\xb1\xd0\xa7\xe1\x44\x44\x49\x49\x66\x67\xab\x35\xa5\x0b\xd0\xf9\x60\x94\x3e\x07\x63\xc1\x55\x56\x4c\xa1\x3f\x28\x83\xb2\x75\xfa\x2c\xb4\xed\x72\x83\x35\x7e\xff\x9e\xca\x36\x2d\x69\xa1\x02\x06\x90\xb0\x88\x28\xb4\x09\xad\x79\x92\xe9\x8f\x1c\xc3\xa2\xf8\x05\x29\x02\xe5\xc2\x05\x85\xfb\x38\xf1\xe3\x40\x85\xbe\xa8\x88\xbd\x20\x5b\xd5\x17\x90\xc8\xd5\x20\x44\x9a\x25\x20\x48\x1d\xf6\x94\x96\x5c\xcb\xf4\xb0\x33\x9f\x07\xb8\x31\x80\xbe\xfc\x2e\x5d\xd8\x59\xfb\x43\xf6\xd6\x48\x9e\x55\x06\x0d\xee\x85\xd2\x4c\xcd\xfa\x24\x99\x93\xc8\x81\x18\x86\x52\x0c\x0a\xdb\x7c\x10\x05\xc9\x44\x48\xdd\xcf\x1e\xbc\xfb\xd2\x8e\xff\xdb\x5c\x39\xe2\xd3\xa9\x90\x83\xa7\x57\xe1\x78\x60\x3a\x7c\xd5\x02\x2b\x98\x70\x65\x34\x10\xc5\xb2\x31\xe5\x4a\x48\xfd\x21\x1a\x08\x57\x89\xe9\x98\x07\xc2\x22\xd8\x56\x44\x96\x97\xdc\x05\x05\x41\xe1\xbe\x22\x6f\x7e\x5f\xa9\xcb\x9a\x96\xfc\x51\xe1\xc7\xb2\x5b\xf4\x2f\x36\xc1\x3a\xa5\x31\xbf\xcf\x64\x08\xef\x89\x16\x4b\x5c\x7f\x3e\xef\x40\xba\x97\x95\x14\x5b\x6c\xad\x62\x97\x0a\x85\x6c\xe0\x05\x30\xf0\x06\x0a\xe3\x1f\x3d\x0d\x43\x8f\x83\xef\x09\xd4\x10\x48\xba\xe2\x83\x54\xff\x1d\x04\xfe\x1a\x89\x3b\xbf\x44\xa2\xdd\x99\x51\x9b\xb4\xf4\xef\x9e\xc4\x25\xc5\xf7\xba\x2d\xa2\xb0\x72\x5a\x19\x20\xad\x6a\x65\xf6\xcd\xf2\x03\x13\x4f\xc1\x75\xa6\x59\x2c\xd6\x08\x0e\xad\xc8\xb9\x04\x75\xb1\x42\xef\xb2\x7a\x63\xca\xb4\x42\x6d\x30\x86\x2c\x0e\xd0\xab\xb0\x64\x61\xcf\x0b\x74\xa7\x2b\xb6\x41\x21\xcc\xf1\x80\x58\x85\xa9\x08\x87\x46\x5c\x5c\x31\xb2\x71\x03\xa0\x84\x0e\x92\x55\x08\xcb\x61\xd2\x8b\x5f\xd8\x20\xa8\x20\x04\xbe\x0a\x65\x35\x72\x7a\xf1\x4b\x5b\x08\x35\xb4\x10\xac\x42\x5c\x8f\xa5\x5e\xfc\xe2\x36\xc3\x12\x72\x88\x56\xa1\x5f\x0e\xae\x5e\xfc\xf2\x66\xc4\x8a\x2a\x20\x5c\x55\xc9\xaa\x60\xeb\xc5\xfa\xc8\x0d\xa3\x9f\xf0\x8e\x53\xd2\x81\x28\x04\x1b\x66\x8a\xc3\xbb\x65\x60\x88\x36\xc2\xee\x54\x60\xc3\x8d\xb0\xbb\x65\xd8\xde\xba\x79\x80\xa0\x7b\x06\x54\x41\xe4\xdd\x0f\xb1\x84\x5e\x54\xa6\xea\x50\x15\xb2\xd4\x31\x6b\xd1\x54\x3b\xc6\xa0\x72\xa6\x8e\x27\xd7\xcc\x51\xd3\x09\x68\xae\x6d\xf7\x67\x84\x2b\x30\x0a\x07\xd1\x4c\x82\x64\x63\x81\xfb\x8b\x11\x35\x02\x47\xb8\xdb\x46\x34\xf7\xef\x88\x2f\x40\x1e\xee\xf6\x63\xe5\x8d\x15\xc4\xc2\xa8\xbe\xc2\xe5\xd4\x9b\x91\xa1\x48\xfd\xc4\x0b\x4a\xbd\x34\x3e\x0d\x44\xb6\x9b\xa7\x20\x5e\xd7\x0f\x8d\x4b\x22\xed\x72\x6c\x44\xa2\x19\xb3\xb5\x3d\x16\xbc\xf3\x0c\x68\xf0\x8e\x02\x7f\xe2\x29\x97\x3f\x01\x7e\x63\xfe\xbd\xa9\x74\x05\xca\xc5\x92\x2e\x78\xbf\x28\x85\x95\xe5\x4e\x23\x0e\x82\x69\x77\x1b\x12\xa6\x5d\x89\x21\x00\x51\xcf\x0c\xde\x16\x63\xa2\x4f\x34\x53\xa8\xba\x12\xf3\x0f\x33\xab\x97\x19\x2c\xc6\x98\x68\x36\x9d\x60\xcc\xe3\xd8\xfc\x48\xfa\x37\x8a\x68\x7b\x5a\x01\x55\x48\x4e\x3d\xfb\xf5\x03\x9f\x88\x1c\x42\x59\x08\x85\x10\x8b\xe5\x30\xb8\x1b\x55\xd1\xbb\x99\x3c\x57\x17\x3d\xf3\x87\x89\xbe\x68\x39\x0d\xa7\xa5\xbd\xd2\x79\xb5\x6d\x55\x75\x7f\x6d\x67\x16\x78\xbe\x45\x60\x20\xdc\x6b\x8c\xf0\xbc\x66\xd2\x9d\x60\xfc\x31\xcd\xbc\x07\x39\xd8\x27\xe9\x06\x4a\x70\x2d\x4e\xc5\x2d\x2e\xe1\x36\xda\x2e\x1c\x92\x3d\x04\x2b\x79\x77\xa5\x7b\x8d\x26\xe4\xf7\x9e\xf9\x24\xdc\xed\x1e\x5d\xda\x03\x48\xfa\x09\x3b\x4f\x40\xb8\xdf\x2f\xbc\x6c\x27\xda\x28\xc8\x46\x69\xb8\xee\xd9\xb8\x8f\xfb\xef\x5e\x02\x53\x4f\x65\x0e\x1e\x12\xb0\x6d\x45\x04\x18\x1b\x59\x8c\x27\x97\xe2\x46\x48\x7d\x69\x54\x8c\x4b\x25\x86\x8c\x43\xb0\x08\x87\x64\xb7\x4c\xf5\x44\x11\x63\xc0\x5e\x11\xe9\x8e\x28\x28\x90\xee\x80\x42\xd0\xcb\x1d\xf8\xfd\xbc\x59\xcf\xc7\xc2\xa8\x3b\x1f\x4e\x88\x74\x87\x80\x1b\x59\xf5\x6f\xb8\xbd\xd5\xfb\x21\x9b\x4d\x87\x9b\xf9\xe2\x06\xcd\x66\xe0\xf2\xc1\xe0\xb9\x21\xe4\x5d\x18\x6b\x21\x85\x22\x4e\x30\x0e\x83\x6b\x07\x7e\x48\x12\x50\x0a\x86\x84\xb4\xe6\xdc\xb9\x18\xa1\x51\xbd\x62\xdb\xe0\xad\x24\x01\x6c\x2b\xd2\x35\x8d\xe8\x47\xe7\xe1\x85\x67\xfe\xe0\x46\x40\xae\x68\x06\x25\x9f\xb6\x5a\x72\xae\x1b\xf3\x4b\x97\x43\x56\x7a\x46\x24\x99\x81\xe8\xaf\xf4\x25\x30\xe9\xc6\xfa\x6e\x2c\x56\x46\xa4\x2e\x88\x84\x84\x7a\xe9\xe4\xaf\x62\x28\xdb\x7e\xd2\x0c\xc8\x8b\x18\xb9\x08\x9f\xcc\x34\x28\xcc\x41\x5d\x84\xf2\x88\x0b\x08\x98\x31\xf5\x0c\xeb\x70\x74\x03\x05\xf6\xaf\xfb\xc3\xdd\x66\x8c\x71\x34\xec\xdc\x1f\x8c\xf7\x82\x48\xea\x50\x26\x62\x21\x5d\x25\x26\xd1\x8d\xa8\x76\xb4\x30\x2b\x50\x50\x38\x34\x42\x30\x53\xb9\x74\xee\x27\xb3\x29\x86\xee\x0f\xd0\xec\x06\x45\x07\xc8\x6c\x0b\x44\xd3\x52\xaf\x41\x62\xc4\x98\xa2\xa0\x98\x76\x39\x70\x96\xf4\x93\xc3\xdd\xbe\x72\xb9\x67\x84\x88\xa7\x40\xb3\xae\x99\xa2\xca\xf5\xbd\x5d\xc6\x92\x66\x13\x65\x4a\xc0\x88\x6e\x36\x4d\x17\x46\xd3\x4f\x2a\x9a\xf2\x11\xb7\xcb\x0d\x90\x9d\x25\xf0\x1b\x6a\x40\xa7\x0a\x19\xf7\x99\x18\xf2\x64\xac\x09\x85\x90\xf6\x04\x0b\xdc\xef\x3d\x1b\xdc\xbb\x1c\xb5\x2e\x28\x67\x82\x70\xda\x43\x1f\x58\xc1\x44\xb9\x35\x12\xb5\xdb\x3d\x03\x73\x1e\x5d\x18\x30\x63\x47\x4c\x17\x01\xe1\xe8\x25\xc9\xd6\x6e\xf7\x07\x93\x30\x5c\x10\x05\x9c\x82\x5c\xe6\x5b\x01\x01\xf8\xaa\xd9\xbc\x9f\xf2\x38\x0e\x6f\x84\x37\x36\x75\x1e\xee\x18\xed\xc1\x08\xb6\xc0\xba\xe0\xd6\x8f\x85\x05\xcb\x54\x3d\x64\x11\xe4\x9d\xdd\x55\xdc\x97\xab\xba\x96\xe3\x4a\xb1\x3e\x3d\xd1\x97\x6e\x2c\xf4\x91\xd6\x2a\xf4\x13\x2d\x88\x3d\x62\x96\xd6\x5b\x7a\x4d\x17\x39\x7f\xee\xfd\xbd\x3a\x20\x61\xc2\x1d\xa2\xb4\x89\x96\xea\xfb\x70\x42\x12\x58\x5d\xa7\xfd\x54\xd4\x7b\xc3\xc7\x89\xc8\x45\xfd\x95\x08\xae\xc5\x20\xfd\x89\xce\x36\xc6\x12\x33\x27\xd0\x0d\x47\x17\x0b\xad\xee\xee\x67\xa1\x1c\x44\xb3\x15\x62\x43\x3b\x76\x57\xe0\x23\x8a\x4a\xd7\x9a\x66\xf9\xa6\xe6\xfd\x02\x9c\x74\x60\x1c\xb8\x1f\x09\xed\x95\x54\x1b\x5f\xb1\xad\x8e\x51\x4d\x8a\x50\x8a\xd2\xce\x55\x65\x09\x38\xcf\xa3\xcc\x47\xa9\xec\x80\x0e\x2d\x9f\x70\x9e\xaa\xb2\x09\x77\xbf\xed\x29\x50\x9e\x86\xd8\x13\xa0\x53\x3d\x1e\x92\x4c\xa1\xcf\x1d\x25\x45\x30\x51\x69\xeb\x45\x55\xce\x7b\x60\xec\x65\x26\x98\xa4\x51\x13\x8c\x36\x61\x26\x63\xb2\xc5\x98\x15\x05\xdd\x2d\xec\xb1\x1d\x7c\x51\xf6\x76\x4c\xcd\xda\xd9\x01\x81\x1b\xa2\x6c\xb5\x1f\xc7\xc8\xd4\x5f\x3c\xcc\x64\x96\xd7\xfc\x48\x5a\x6a\xc9\x49\xd7\x18\x4a\xd2\x1d\x80\xf0\x04\x0c\x3d\xb3\x0e\xf8\x9e\x74\xfd\xc5\xc2\x08\x06\xce\xba\x8b\xd4\xf7\xc4\x53\xcf\xd3\x7e\x65\x37\x78\x0c\x91\xa9\x1c\x42\x16\xe4\xfb\x8a\x2c\x64\x8c\xe5\x12\x7e\xd8\x6c\x86\x66\xa6\x0e\x59\x70\x1e\x1a\xe6\x30\xb2\xdd\x74\xc0\xb0\xdc\x56\xa2\x70\x21\xbe\xa6\x3d\xf3\xa0\xcc\x8a\x6c\x15\xa3\xda\xd8\xb9\xd7\xa0\xdc\x6b\xf0\xcd\xf8\x61\xb9\xce\xa1\x9f\x47\x97\x61\x7f\x75\x41\x80\x4f\xf3\xd0\x91\x8c\xd8\xd8\xac\xcd\x30\x66\xca\xfd\x0e\x03\xb6\xd5\x85\x1b\x53\x1d\x2e\xd6\x37\x66\xb1\x1e\xb0\xad\x0e\x2c\xad\xd8\x71\x3f\x66\xe7\x31\xdc\x98\x15\x3b\x4e\xc3\xb7\xcd\x8a\x7d\xc3\x6e\xdc\xeb\x7c\x65\xdb\x66\x2a\x45\xb5\xbd\x1e\xd5\xb8\x3f\x66\xe7\x63\xd8\x36\xa8\xc6\x16\xd5\xb6\x41\xb5\xcd\xb6\xdd\xeb\xac\x89\x83\x66\x33\x4e\x9b\xb3\xc5\xd8\x38\x7d\xec\xd7\xb9\xc1\x23\x64\xb0\x6e\xda\xb3\x4e\x4f\x1f\x16\x67\x0c\xec\x4e\x9e\x3c\xd7\x17\x86\x13\xcf\xf5\xc5\x8a\x6d\x3c\x12\xc3\x98\x7a\x31\x63\x6c\x4c\xe7\x73\xac\x67\x07\x04\x8c\x6d\x17\x9b\x7e\xbf\x81\x6d\xc3\xd2\xad\xee\xd2\xde\x37\x0e\x82\x74\x39\xee\x2b\xf2\x74\x0c\x76\xd1\x8d\xcd\x97\xb6\xd1\x11\xdd\x2c\x9f\x21\x70\x5b\x0f\x33\x5a\x82\xb8\xce\x20\x76\x3d\xdc\x3f\xbe\xc2\x7a\xae\xd6\x4e\x13\x9f\xdd\x19\x2e\x19\x80\x32\xaa\x87\x9f\xd2\xb3\x87\x3c\xd1\xf3\x99\x72\xc3\x62\xc3\xb5\xdc\x82\x0c\x72\xdf\x72\x4f\xd9\x81\x5c\xa2\x26\x49\x97\xf4\x5e\xbe\xa1\x6c\xd6\xb6\x74\x37\xb7\x4f\x08\x2f\xd7\x4e\x4b\x95\x73\x63\x8c\x66\x72\x81\x7a\x25\x8a\x4b\x67\x8e\x55\x4d\xc1\xc8\x2c\xb5\x22\xf4\x43\x52\xa3\xd6\x6c\xe1\xd2\x6a\xd4\x93\xec\x69\x37\x7f\xda\xc3\xa7\xbe\x0d\x14\xe9\x93\x88\xc9\xf3\xe4\x82\x32\xc6\x88\x0d\x73\xa6\xcd\x66\x2a\xbf\xd3\x12\x99\xfc\xb6\x32\x28\xd5\x79\x74\xb3\x49\x48\xc0\x22\x6a\x94\x13\x12\x31\x4e\xdd\x6d\xdc\x86\x0e\x5c\x0e\x51\x7a\xdc\x8a\x08\x26\xec\x7e\x8b\xd5\xeb\x2b\xbf\x75\x3f\x55\xc0\x74\xdf\x71\x32\x55\x4a\x9b\x0a\x76\xed\x5b\x2b\x4b\xd1\x56\x33\x62\x69\x08\x51\x26\x5e\xbd\xe5\x93\x3e\xe7\xc9\x85\x41\x63\x56\x0a\x2f\xed\xe4\xec\x68\x9a\xa9\x11\x12\xd3\xd9\x75\x82\xb0\xdb\xc2\x34\x62\x06\x7b\xaf\x42\x74\x68\x04\x62\x58\x3e\xdb\x59\x1c\xe2\x2e\xc9\xf0\x4c\x72\x0b\x94\xdc\x02\x24\x4b\x32\x41\xa7\x18\xcf\xa6\x99\x3a\x94\x7d\x1c\xd4\x03\x10\x70\x7f\xe3\x29\x08\x3d\x3c\xdc\xe0\xc9\x43\x95\xf2\xc1\x43\xfb\x49\x82\xf0\xf8\xa2\x50\x8b\x03\x26\x0f\x55\x1f\x2d\x57\xd6\xe9\x45\x87\x41\x2f\xca\x82\x41\x42\x96\x9c\x47\x17\xbd\x91\x22\x21\xf0\xf3\xe8\x02\x34\xb4\x5a\x36\x76\x35\x44\x67\x54\x89\x4b\xaf\xd5\xea\x03\x39\xc0\xd9\xfd\x22\xf3\x45\x5b\x05\xdc\x34\x63\x98\x0b\x68\xf0\x59\x98\x3d\xc6\xac\x03\x63\xd6\x81\x01\x13\xbd\xf8\x70\xd8\x6c\x8e\x0f\xfd\x74\x83\xf5\x06\xb6\x19\xb9\x61\xd1\x79\x7c\x41\x5d\x0e\x13\x46\x9e\xb3\xf0\x7c\x8c\x3f\xae\xd8\x8d\xeb\xc3\x94\x3d\x77\x7d\x23\xd8\xb7\xb7\x18\x9b\xd8\x52\x23\x98\xc1\x1d\xdc\xc2\x35\x1c\xc1\x89\x29\xdc\xea\x5e\xc0\xa9\x29\xd8\xea\xe2\x22\x70\xd2\x6c\x92\x19\x3b\x71\x7d\xb8\x63\x13\xc3\xa6\x23\x76\x62\xf8\x0b\x4e\x9b\x4d\x72\xcd\x4e\x5d\x1f\x8e\x98\xd1\x90\xc9\x2d\x3b\xc5\x0f\x47\xcd\xe6\x1d\x1d\x29\x72\x05\xd7\x90\x40\xab\x35\xa0\x70\xa2\x30\xd9\xc4\x36\x4c\x61\x6c\x54\xb2\x41\x8b\x5d\x59\x4f\xe1\x69\xf6\x65\x66\x21\x07\x2d\x36\xb3\x5f\xe2\x16\xdb\x81\x71\x8b\xed\x58\xfd\x32\x1c\x92\x23\x3a\x68\xb5\x32\x5c\x93\x0c\x57\x5e\xd3\xa0\x8c\x37\x6e\xb1\x6e\xb5\xf4\x1d\xcd\xeb\xba\xca\xeb\x4a\xa1\x47\x8a\xcc\x60\x9a\x51\xbb\x4c\x43\xb7\x97\x6d\x2e\x6f\x9d\xcc\xe7\xa3\x2d\xc6\x6e\xa9\xaf\x04\xbf\xee\xd5\x71\xd6\xa9\xab\xd5\x71\xbd\xbe\x8e\x9d\x85\xd5\x64\xb1\x3d\x65\x5a\xf2\x16\xb5\x60\xdc\x6a\x2d\x70\x5b\x20\x3e\x1c\xf6\xb2\xf6\x94\x06\xdd\x8e\xf3\x72\x41\x7b\xbc\xb2\xe0\x95\xe7\xf0\x8d\x7d\x9b\xcf\xcf\x2f\x7a\x29\xbd\x25\x5e\x79\xee\xfa\x90\x2a\x54\xdf\x28\xd6\x48\x3a\x87\xd9\x94\x9a\xcf\x3b\x87\x41\xfe\xfc\x2d\x93\xa0\x8f\xcc\xcc\x99\x79\x09\xdc\x7a\x01\xdc\x79\xdf\xd2\x0d\x9f\x23\xc5\x9c\x4b\x31\x9e\xfc\x7e\xf0\xe4\x5d\x29\xa9\xcd\x89\x5a\xb5\x35\x8d\xe7\x0f\x4d\x0f\x07\xd9\xda\x91\x1e\x0a\xbb\x57\x5e\x02\x47\x5e\xc0\xee\x03\xaf\x03\x3f\x3d\x01\xe6\x45\x9c\x7b\x6f\x53\x3d\xc3\x94\x67\x01\x9a\x51\xc6\x4e\x0d\xdc\x80\xde\xd7\x30\x2c\x28\x04\x6e\xc0\x76\xd2\x1d\xee\x8a\xe2\x12\xb8\x3f\x41\x40\x04\x81\xab\x0c\x94\x62\x89\x45\x1b\xb8\xb1\x1b\xb3\xfb\x99\x17\x59\x0c\x8b\x8c\xfa\xd6\x91\xca\x5c\x99\x45\x70\xca\xf2\x4a\x94\xb7\x8b\xe7\xc1\x05\xdc\x92\x96\x11\x12\x54\x09\x11\xc0\xdd\x9f\x10\x40\x92\x2e\xee\x53\x45\x14\x3c\x86\xc4\x74\x70\x00\x47\x46\x34\x2d\x4e\xab\x34\xd8\x30\x84\x7b\xc5\x72\xd8\xcc\x83\x8e\x9d\x72\x1f\x78\xdd\x52\xbf\xa9\xf2\xda\xf9\xbc\x24\x95\xb6\x4a\xdb\xe6\x35\x8f\xa9\x15\x76\x46\x49\xed\xd9\x70\xbe\xd0\x55\x96\xa9\xcc\xda\xca\x53\xb6\xf2\x21\x66\xa1\x55\x9e\xcd\x10\xc4\xfd\xe7\x86\x1e\xed\x5e\x43\xe8\xc6\x10\x51\xef\x11\xbe\x25\xa1\xab\x99\x82\xd0\x4d\x58\x04\x9d\x43\x62\xe4\x5b\xec\xce\x68\xae\x26\xda\xea\x7d\xe8\xa4\xd5\x53\xef\xf1\x72\x41\x62\xea\x8a\xcd\xb2\x12\xbb\x47\x6e\xcc\x94\x45\xb5\x19\x11\xf5\xca\x38\x28\x6c\x11\xd3\xaa\x56\x0b\x37\x4b\x09\x36\x8b\xfe\x33\x67\xc0\x04\xb9\x78\xcc\xb4\x6d\xd3\x1e\xea\x5f\xb9\xf0\x1e\x30\x9d\x2a\x95\x03\xab\x54\x0e\x0a\x35\xd1\x54\x3c\xb0\x1d\xd8\xea\x42\x00\x6a\x85\x6b\xc8\xce\x91\x1b\xa6\x5d\xd1\xcb\x94\xd4\xe0\x2a\x1c\x0f\x3e\x44\x03\x11\xe7\xcb\xcf\x84\x75\x7a\x93\xc3\x9b\x6c\x21\x9b\x64\x6b\xcf\x95\xb1\xfc\xd9\xb8\x7f\x73\x3e\xb9\xf0\xcc\x1f\x94\xf0\xad\x16\x6f\x11\x3b\xf1\x71\x2a\xf0\x43\x36\x6c\x36\x87\x87\x6c\xda\x6c\x92\x84\x49\xb2\x7d\x3e\xb9\x80\xab\x74\x6c\xa7\x90\xf7\x41\xad\x07\xf2\x2e\xe8\x71\x36\x5d\xe4\xfd\x91\xd9\x66\xd0\x01\xe5\xfa\x50\x4e\xac\xf2\x4d\x2d\x6d\x5a\xa0\xab\x2e\x53\x91\xa5\x47\x4a\xcc\x06\xdf\xcd\xb3\x2e\x07\x26\x7e\x57\xab\x14\x65\x55\x56\x94\xeb\xb6\xb2\x06\x51\x8b\x1c\x59\xda\x87\xcf\xf5\xe0\x95\x4e\x22\x26\x4b\xdb\x7f\xa0\xd9\x36\x32\x2c\xed\xe9\x15\xe3\x35\x9f\x93\x55\xaf\xad\x97\xa9\x3e\xb6\x3d\xd1\x6c\xea\x2d\xc6\x64\xb3\x59\xdb\x56\xd4\x20\x4b\x47\x98\x71\xb7\x3c\x06\xe5\x26\xb5\x58\xfa\xd4\x89\xe6\x26\xe6\x3b\x85\xfa\x66\xbb\xcc\x90\x3e\xe3\x9a\x93\x0e\xc8\x5c\xe7\x29\x41\xe7\x6a\xbd\xed\x5a\x37\xae\x2b\xf3\xab\x48\xef\xaf\x7a\xe9\x7e\x67\xca\x8d\xbd\x55\x9f\xd8\xfd\x77\xcf\x34\x61\xea\x29\x37\x59\x64\x55\x1f\x78\xe5\xf3\x53\x71\x9a\x86\x45\xbb\x21\x86\x2e\x66\x1e\x0c\xdb\x23\xb2\xc4\xf6\xe7\xda\xbd\x29\x54\x3e\x99\x85\x83\x16\x0a\x13\x41\x7c\x14\xd5\xbd\x4a\x41\xc1\x4c\xd1\x9e\xc8\xd7\xaa\xb4\xa6\x50\xc6\x42\xe9\x27\x62\x18\x29\x41\xb6\x15\x49\x30\x5e\xd2\x4d\x28\xf0\x7a\x3d\x8f\x8d\x09\xb3\x95\xd6\x40\x0b\x27\x42\x79\x83\xb8\x44\xb6\xe9\x67\x2b\xc0\xb5\x7b\x54\x36\x56\x1a\x9d\x2d\xb3\x00\x29\xf4\xab\xad\x2d\x1c\xb8\x31\xb3\xb3\xc0\x9d\xe5\x43\xf6\x68\x15\xbb\x66\x5e\x12\xdb\x91\xd5\x2f\xe1\xb0\xec\x6e\xd0\x2c\x77\x0f\x3f\x4b\xb7\xca\x5f\x28\x3e\x42\x3f\x71\x9e\x0b\xa7\xdc\x3f\x99\xfa\x7c\x2e\x2e\xdc\xa3\xde\x5b\x69\x2c\x4b\xc6\x58\xe2\x06\xfd\xc4\x8d\x3d\xd3\x5f\xee\x4f\xec\xae\x52\x24\xd3\x82\x68\xf7\xce\x1e\xda\xcf\x1b\x50\x64\xae\x60\xda\xbd\x4d\x03\x13\x92\x72\x60\x42\xba\xce\x27\xe7\xdc\x68\xba\x81\x7b\x04\x11\xdb\x41\x47\x44\xd0\x8f\x6c\x5d\x51\x5a\x57\xaf\x36\x6c\x11\x54\x86\x3a\x70\xd5\x05\x5d\x88\x66\x13\x77\xfe\x45\x29\x30\xc6\xe6\x55\xa8\x1e\xef\x50\x6e\x4c\x24\xed\x0d\xac\x67\xd3\x9b\x92\x6e\x87\x2e\x16\x24\xc1\x74\x21\x0c\xa7\x28\x91\x4c\xe4\xed\x2b\x85\x6a\x3e\x55\x69\x04\xa4\x4d\x2e\x65\x58\xfe\xf4\x6e\x2a\x32\xd6\xf8\x5d\x12\xe9\x6a\x71\xab\x9f\x46\x52\x0b\x69\x8f\xff\x75\xb7\xd6\x80\x3a\x4e\xd1\x49\x59\xa2\x01\x9e\xb9\xf0\x62\xa8\x1f\xef\x2c\x9d\xee\x54\xec\x35\x99\x91\x50\x41\xe2\x4a\x3e\x11\x90\xb8\x68\x21\xe2\x8e\x48\x71\xe2\x5e\xba\x9a\x8f\x3e\xf0\x89\x70\x75\xf4\x2e\x9a\x09\xf5\x94\xc7\x82\x50\x08\xd8\x19\x5a\x16\x45\x07\x82\x28\xbc\x3f\x58\x57\xc0\x5e\x93\xa7\x8a\x44\xe7\xe2\x82\x42\x90\xf7\xe7\x1d\xf9\x03\x8f\xa9\x42\x50\x89\xa5\x50\x20\x41\x97\x36\x69\x31\xd4\x10\xf3\x78\x3c\x33\x7f\x1e\x9b\x3f\xa5\x60\x45\x3c\xcd\x9e\x45\xd8\x0f\x7c\x48\x58\x80\xdd\x03\x9c\x3d\x55\xa5\x48\x95\x77\x95\x78\x8b\xdc\x4d\x2e\x70\xa2\xb1\x2b\xa3\xa8\x2a\x33\x62\xdf\x14\x31\x6b\x97\x59\x3d\x8c\xc9\xb7\x28\x36\xe2\x2f\x2b\x5b\xe8\x96\x4c\x51\x25\x53\xac\x25\x53\x80\x2c\x85\x33\xdc\xa2\x6b\xfc\xd6\x1e\x01\x40\xb2\x03\x33\xb5\x74\xa8\xc7\x02\x22\xf3\xe8\x47\x83\x3b\x08\x4d\x13\xa2\xf5\x4d\xf8\x21\x59\x62\xc3\x18\x18\xc7\x33\xff\xec\x0f\x49\x1c\x53\xd4\xa1\xe4\x8c\x12\xe5\x06\x3c\x6d\x5d\x68\xd6\x9d\xc8\xb4\x2e\x82\x10\x0c\x5b\x43\xc8\x34\xfc\x90\xac\x03\x01\x3a\x55\x82\x83\x66\x93\x64\x44\x30\x3c\x0e\x7d\x40\x6d\xf3\xe1\x8d\x5a\x19\x38\xa3\xc4\x8f\x44\xc4\xfa\x48\x86\x13\xdc\x01\x78\xa1\xf8\x44\xf4\x57\xbe\xad\xc4\xfd\x94\xe2\x9d\x24\x74\xc5\xee\x83\x83\x0e\x2d\x45\xdc\xbc\x53\xc4\x7a\x62\x89\x4e\x4f\xc0\x94\xa3\xa3\x39\xa1\xf7\x09\x6a\x27\x49\xbf\xe3\x91\x37\x8a\x70\x0a\xb8\xd3\xda\xcd\x27\x59\xed\x24\x1e\x93\xa0\xfa\x04\x61\x50\xfc\xa0\xb2\xd2\x35\xea\x5a\xc7\xfe\xb4\x48\x12\xb6\x53\x8e\xa2\xff\xa0\x8a\x0d\xf4\xe7\xc2\x74\xcd\x38\x0a\xb0\x45\xee\x95\x59\x84\x5d\x3e\x9f\x4f\x49\x97\x2e\xd6\xc6\x33\x46\x11\x7c\x13\x95\x90\x2f\x7a\xaf\x9a\xcd\xab\x30\xd6\x91\xba\x73\x47\x11\x51\x14\x24\xb1\x69\x1a\xb0\xa5\xaf\xd6\xee\x02\xaf\xc6\x96\xa1\x32\x86\xc8\x89\xe6\x5a\xa0\xcf\xdc\x81\x12\x5e\x38\x53\x6b\x53\x28\x6c\x46\x9a\xea\x00\xeb\xf0\xde\xd7\xdd\xf9\x65\xef\xfc\x02\x56\xec\x98\x78\xd5\x80\x62\x78\xbd\x9a\xad\xec\x6e\x41\xdf\xfe\xe3\x9d\xa9\xf2\xbe\x7f\x35\xd0\xe4\x52\x92\x5a\x40\x5d\x39\xb7\x29\xbd\x7f\x2a\x49\x82\x01\x60\x45\x82\xd3\xe5\x1d\x20\x55\xdd\x01\xc2\xd3\xd2\x25\x42\xf5\x9a\xbd\x1f\x1b\x72\xb7\x2a\x86\x22\x3d\xc3\x53\x3e\xc5\xa4\x68\xff\x5a\xe3\x2e\xbe\x77\xa4\xcb\x7b\xf1\x1f\x53\x5e\x5f\x11\x3d\xab\xe8\xfd\x1b\x55\x1e\x17\x1b\xe8\x9e\x05\xa9\xb9\x23\xa1\xd3\x4d\xda\x27\x77\xaf\x07\x66\xae\x28\x22\xfb\x47\x92\x18\x99\x46\xbd\x13\x49\x06\xb8\xe1\x67\x27\x31\x46\xed\xaa\x6a\xd4\x6e\x11\x28\xf7\xb1\x2e\x5a\xb2\xd5\xea\x5c\x5d\x10\x0a\x4f\x37\xc5\xed\x6a\xb6\x1c\x70\xf2\x5a\xb9\x71\xa0\xa2\xf1\x18\x21\xe1\xe9\xa2\x1e\xf8\x58\x6d\x19\x86\x3a\x6a\x42\x4b\x67\x06\xf4\x86\x78\x8f\xf5\xe4\xa6\xb5\xbe\x13\x43\x63\x86\x65\x3f\x4f\xa3\x29\xd3\x69\x23\x0c\xee\xaf\x8a\xfd\x55\x82\x99\x5c\xe3\x0d\x98\x6a\xf1\xc3\xc2\xeb\x17\xb1\x4e\x2f\x68\x36\xa3\x43\x6e\x17\xd1\xd0\x68\x33\xc5\x21\x7d\x63\xde\x33\x79\x1e\xb5\x5a\xb8\x11\x76\xae\x5a\xad\x8b\x66\x93\x74\x3b\x8c\x85\x7d\xa2\x5b\x2d\x10\xac\x4b\x3d\x22\x5a\x2d\xc0\x34\x0e\x8c\x91\x83\xdd\xbd\x47\x8f\x9a\x21\xed\xd7\xca\x79\xdd\x62\xff\xfb\x0d\x09\xfa\xca\x6b\x77\xd3\x28\x2c\xf8\xb9\x21\x2a\x4c\x1d\xe6\x66\x51\xb5\x0a\x5d\xa5\x94\xf6\x25\xd1\x6e\x9c\xf8\xb1\x36\x86\xc9\x0e\xa5\x7d\xd5\xda\xf1\xda\x5d\x4f\x12\x7d\xae\x2e\x68\xdf\xf9\x53\xa2\xbb\xf6\x5c\x5d\xf4\xdb\x3b\x9e\x6a\x75\xcd\xd7\x76\x77\x41\xe1\xd9\xa6\xb0\xb4\x6a\x3d\x46\xbb\x59\x50\x78\xa9\x56\x66\x41\xe8\xc9\xc2\x0a\x93\x99\x22\xa7\xab\xa9\x0f\xec\xfe\xb5\x3e\xdc\x7b\x34\x9f\xef\x3f\x2c\x32\xa8\xc9\x42\xab\xa2\xf0\x42\x6d\x4c\x6f\xd1\xe9\x15\xfd\xd2\x53\x85\x72\x5a\x23\xb6\xbd\xf7\x08\xb7\xe7\x0e\x3b\xf3\xb9\x3c\x64\x49\xea\x89\x13\x4c\xfe\x26\x5a\xc9\x22\x8f\xc9\x51\x76\x1c\x3e\xab\x0d\xa9\x1d\x3a\x2b\xdb\x26\x56\xb5\x6d\xef\xd1\x3f\xc5\x7c\x2e\xfe\xb9\xff\x90\x86\x43\x72\xb0\x6f\x7f\x3d\xec\xa0\x7e\x28\x0e\x1f\x3f\x9c\xcf\xbb\x9d\x9d\x43\x91\x92\xa3\x59\xf7\xe0\x37\xdd\x12\xed\x47\x0f\xad\x5f\x2f\x7f\xb1\xbf\xdf\xab\xbe\xd8\x7b\x54\x10\x2d\x31\x1c\xb0\xf7\x57\xcc\x9f\x94\xf2\x26\x20\x43\xf3\xc3\x4e\x3f\x9b\x01\x1e\x6f\xc9\xc2\xef\x1d\xa4\xce\x99\xa8\x36\x0d\x5a\x2d\xda\x33\x4c\x1f\xf5\x89\x60\x5d\xd0\x36\x9d\xcb\x12\xd3\x47\xb4\xd9\x34\xb0\x8b\x9c\xcd\x79\xca\xe1\x36\x7d\x4e\xa5\x77\xcb\x11\x81\x35\x41\x69\xe3\x3a\x24\x93\x62\xd6\x38\x7b\xff\xee\x95\xd6\xd3\x63\xab\x86\x98\x91\x83\xd3\x21\xd1\x8c\x53\x63\x2d\x2f\xef\x41\x4f\x55\x34\x52\x22\x8e\x9d\x8a\x44\xc9\xda\xf8\x34\x9a\x4c\x13\xcd\xfd\xb1\x68\x36\x9f\x9a\xf9\xc2\xc9\x7d\x10\x78\x46\x19\xe0\x03\x31\x80\x60\xe0\x49\x57\x47\x9a\x8f\xed\x6a\xb0\x22\xc8\xc0\x11\x4a\x45\xca\xa9\xc4\xe5\x91\x13\x49\x8e\x86\x6b\x4b\x68\xab\x1e\x2d\x97\x39\x59\x5f\xc6\x10\x54\x2b\xb0\xca\xcc\x5b\x71\x74\x62\xc0\x71\xd7\x3f\x9e\x46\x32\x16\x5f\x8e\xdf\x81\x7f\xe2\xdd\x07\x57\x9e\x74\x63\xcd\x75\x12\x43\xf0\x2e\x7f\x3e\x15\xb7\x7a\x01\xc1\xcf\x15\x47\x5c\xb6\x23\x9b\xa0\xa4\xc8\xc2\x56\x4c\x05\x99\xe6\x78\x71\xfe\x54\x7f\x4a\x87\xc2\xea\x74\x33\xc0\x21\xb0\x46\x89\x31\xe1\x32\x26\x74\xbc\x86\x43\x7b\x9d\xc3\x08\xf5\xb6\x20\x95\x58\xa1\x1c\x91\x0e\x44\x46\x83\x2e\xbf\xda\x69\x45\x14\x14\xbb\x23\x1f\x86\xe5\xe4\xdf\xc5\x1a\x71\xad\xc9\xa9\xb1\x6a\xfb\xbc\xe5\x00\x66\x55\xe0\x1e\xa7\x0b\x3c\xc6\x9a\x87\x9e\x11\x69\x96\xd7\xa3\xf1\xf8\x38\xed\x95\x57\x82\x0f\x84\x8a\x09\xa5\x10\x94\x7b\xcb\x1e\xb9\xc2\xbd\x49\xdb\x3f\x87\x3b\x9d\xce\x7c\xbe\xdb\xe9\x1c\xb2\xec\x15\xcd\xc5\xa2\x51\xcd\x59\x51\xd8\xf4\x25\x9c\x48\x72\x3b\x34\xeb\x74\x4f\x31\x45\x74\x4d\x6b\x38\xb2\xb1\x7f\x1e\x59\x5b\x78\x46\xee\x86\x36\xa1\x98\x59\x3e\x89\x84\xc4\x0d\x70\xf3\x75\x41\x7b\x5a\xdd\xdd\x4b\x37\x9a\x0a\x49\x12\x37\x78\x0f\x89\x3b\xe0\xb0\xd5\x59\xce\x3e\x81\xbc\x75\x3d\x24\x06\xc0\xa0\xd9\x5a\x9f\xad\x26\xf8\xd9\xd3\xae\xdf\xb3\x59\xe3\x30\x88\x24\x9d\x69\xb6\x8b\xcc\x0c\xb1\xd9\xcd\x5c\xdf\x58\xda\x39\xb9\x77\x53\x14\x7c\xca\xf5\x41\xba\xb3\x50\x5f\x3d\x55\x62\x20\xa4\x0e\xf9\x38\x36\x36\xd0\xc0\xcc\x52\xe5\x06\xfb\xd4\x58\xcc\x6e\x3a\x03\x4c\x91\x7d\x97\xdb\x86\x65\xe9\x05\x12\x37\xe0\x45\x14\x46\x2c\xe4\x80\x3c\x1f\x12\x41\xfb\x64\x05\x3d\x4e\x6a\x3e\xb7\x0d\x05\x8e\x3d\xec\x2e\x5c\x9f\x7a\xf8\x54\x56\x42\x5c\xee\x47\x4a\x13\xba\xa8\x6b\x3b\xd5\x50\xd3\x0e\xf8\x9e\x76\x7d\xe0\x95\x29\x20\x99\x11\x0d\x85\xf3\x6d\x46\xbe\x0d\xf3\xfc\xf4\x48\xf7\x17\xb5\x26\xad\x8d\x33\x72\x7a\xd2\x0d\x3e\x36\x9b\x44\xb7\x98\x33\x71\xcc\xfc\x0e\x44\xfa\x33\x74\xec\x38\x16\xec\x7b\x2c\x46\xcf\x6f\xa7\x48\xd5\xf2\x48\x1e\x69\xa3\x59\x3f\x59\xaf\xf3\xcb\x64\x3c\x46\x83\x6f\x92\x96\xdc\x9c\x52\x16\xd2\x5d\xc4\x8e\x99\x99\x36\xd4\x24\x4b\xe1\x03\x11\x6b\x77\x7b\xbc\xd5\x3a\x94\xcd\x26\x86\xc3\x8a\x5b\x11\x90\x80\xd2\x66\x33\xda\x2a\x43\xf6\x0a\x84\x61\x1e\xc1\xd5\xee\xc2\x30\x0d\x57\x09\xcd\xf4\x0e\x33\x3f\x3f\x13\xe7\xe1\x45\x6f\x78\xde\x6e\x87\x17\xcc\x37\x8a\xb3\x8f\x6a\x73\x92\xa5\xf1\xfb\xee\x83\x38\xef\x5c\x80\xb0\x22\x02\x38\x1c\xe3\xa9\x7d\x1b\x8c\x92\x55\x9a\xcf\xe6\xe2\x15\xd3\x90\x26\x18\xd4\xe5\x65\xc5\x66\xcb\x4a\x3d\x48\x9d\x3c\xdf\x5d\x66\x00\xd5\x74\xcd\x70\x48\x82\x56\xeb\x9f\x2c\xc9\xb5\x90\x92\xe3\x85\xab\x11\x6a\xe7\x59\x18\x47\x7b\x17\xb2\x74\xd1\xca\x34\x52\xe5\x29\x9e\x72\xc8\x73\x75\xd1\xd3\xe7\xed\x36\x86\xb3\x5e\x6b\x22\xb0\xb1\x79\x9e\x7f\x6c\xae\x84\x02\x7c\xa9\x8a\x9d\x0b\x08\xe0\x38\x57\xf5\x29\xfc\xd8\xac\x09\xe9\x6c\x4c\xcb\x63\x59\x19\xd9\x9e\xcc\x65\x72\x90\x0d\xab\xa0\xe9\xfe\x99\xd5\x40\xf2\x00\x56\x7b\x78\x87\x43\x2a\xaf\x29\xad\x22\xce\xbd\xfb\x35\x78\x4a\x61\xe5\xc0\x7c\x5a\x6b\x01\xcb\xe6\xa6\x14\x75\x1b\x33\xe0\xfd\x8f\x0d\x25\xd5\xe1\xa1\x5c\xd0\xde\xd9\xda\x7a\xd5\x3f\xff\x29\x37\x64\x3a\xfe\x27\x7e\xee\x55\x12\x2c\x8a\x75\xc7\x21\xf3\xf3\x5e\xaf\xa5\x16\xea\x86\x8f\xcb\x56\xd0\x53\x49\xc4\xc6\xd3\x5e\x79\x21\x45\x6b\xe7\x71\xdf\x96\xa2\xdb\x1b\x33\xf2\x5d\x83\xf3\xa7\x6c\x34\x1a\x0d\x07\x66\xe4\x29\xfe\x72\x40\x96\xf7\x43\x7e\x2f\x97\xb8\x23\x97\x7a\x6d\x03\x5b\x46\xdd\xef\x18\x49\x96\x17\xfe\xa3\x5c\xf8\xf1\xc3\x43\x46\x24\x3b\xc3\xa3\x56\xcd\xa6\x3c\x64\xdd\x9d\x9d\x02\x56\xea\x02\x36\x07\x3b\x64\x8f\x3b\xcd\xe6\xc1\xfe\x21\x2b\xf9\x43\xd5\x6a\xc8\xfd\x87\xcd\xe6\xde\xa3\x0a\xa4\x2e\x41\x5a\x62\xe6\x73\xac\x67\x3e\x47\x24\xa5\xbb\x30\x74\x25\xbb\x40\x71\x01\x45\xe5\xbd\xcb\x4b\x37\x3c\xac\x29\x11\x94\xde\x3b\x0e\xda\x34\xa8\xf8\x6a\xf6\x11\x42\xcd\x26\x30\xd4\x8c\x54\x3c\x15\xa5\xc3\xc6\xca\x0d\x30\xbf\xf0\x00\x92\x75\x6c\x76\x47\x42\x0d\xd2\xdd\xee\x6b\x2f\xc1\xd8\x69\x6e\x46\xb8\xfc\x31\x01\xfc\xc7\x22\xb6\xe6\xc7\x9a\x73\x7d\x36\xaa\xb6\xbd\x83\x3b\x64\xdb\xd5\xac\xb8\x46\xf3\x32\x64\x48\xe0\xec\x0e\xdd\xeb\x3e\x68\x37\x80\x3b\x32\x44\xcc\xa0\x5d\x81\x39\x91\x13\x50\x8c\x83\x66\x02\xcf\x7f\xf8\xab\x34\xc7\x06\x16\x5a\x6b\x07\xce\x48\xa4\xc1\x66\x18\x46\xc3\x03\xce\x0c\x17\x41\xbc\x12\x95\x64\x12\x7e\x01\x9d\x2c\x63\x1a\x6b\xd6\x85\x81\x66\x3b\x70\xa3\x59\x07\xb6\xf5\x5a\xd9\xb1\xa0\x30\x59\xa9\xfb\xe6\x39\x20\xe0\x4a\x6f\x3a\x0f\x9c\xa7\xf9\xa5\x30\xdd\x00\xd8\x29\x03\x8e\x36\x00\x76\xcb\x80\xb3\x35\xa4\xa5\x27\xfe\xe0\x6e\xcd\xf7\x9d\xf4\xfb\xad\x66\x2f\xe1\xfa\x2f\x90\x1c\x69\x66\xea\x5d\xc0\x89\x66\x4a\xc2\xa9\x66\x1f\xe0\xb9\x66\x33\x09\xdf\x56\x0f\x48\xcb\x71\x16\xf0\x5d\xaf\xf7\x48\xfe\x01\x12\xbe\xda\x3c\xb3\xf0\x74\x2d\xdc\x31\x99\x91\xdf\xc1\xe6\x89\xa1\x70\xa9\xd9\x46\xa6\xdd\xd2\xf5\x34\xce\x02\xf3\xe9\x5a\x86\xc5\x3c\xff\x59\x4a\xe7\x32\x83\xc2\x1b\xcd\x7e\xc2\xbb\xbf\x40\xde\xcd\x52\x67\xe7\x2a\x79\x5a\x83\x84\x84\xa9\x76\x17\x6b\x88\x34\x96\xeb\x49\x26\x40\xb1\x04\x34\xe3\xa6\x82\x0f\x7a\xfd\xcc\x7d\x67\x67\xce\x99\x69\xe0\xab\x0d\x70\x6f\x0c\xdc\x8c\x7c\xd0\xd0\x81\xdf\x15\x51\xb4\xdd\xa5\x36\xd7\xf7\x59\x75\x08\xb2\xe0\xde\x92\x49\xdd\x29\x65\xf4\xae\x24\x00\x55\x7d\xe5\x75\x3b\x3b\x7b\xbf\x11\xd5\xc6\x0f\xb4\x55\x29\xd8\xa5\x6d\x4c\x16\xd9\x3a\xd8\xdf\xdf\x3d\x58\xc0\xeb\x35\x33\xf9\x52\x43\xa4\xd3\x89\xf5\xf1\xef\x90\x83\xae\xcd\x3a\x4d\x97\x44\x1a\x15\x4d\xa6\xeb\x7d\x97\x52\xcf\xbe\x6a\xc9\xf3\x6e\xf1\x7e\x87\x52\x54\x77\xe0\x78\x5d\xb7\x39\x7f\xca\x3f\x25\x71\x5a\xdf\x34\x91\xad\x2e\x6d\x11\x87\x36\x9c\xd6\x5b\x45\xbe\xea\x34\x91\x09\x7c\x5d\xd9\xa2\x19\xf9\x69\xba\xfb\x8c\x2e\xe0\xe7\x32\x72\xe9\xa5\x7c\xb1\x22\x03\x51\xf9\x08\x94\x44\xde\x5b\xf2\xc2\x7e\xcc\xf2\x71\x76\x6d\x32\x87\x22\xac\x36\x4f\xf7\x00\xb2\x74\x05\x08\xf9\x43\x11\xb3\x00\x70\xbb\x52\x29\xb3\x52\xce\xc8\x89\x06\xad\x4d\x87\x13\xa3\x35\x19\x5d\x1b\xd9\x2f\xe9\x3b\xae\xd3\xd2\x9e\x73\xfe\x0f\xcc\x56\xf6\x8f\x0b\xc7\x72\x3c\x37\x0c\x99\x1f\x11\x69\xe4\x1b\xf1\x59\xb4\x81\x0f\x01\x73\xce\x6d\x5f\xb9\x9c\xb6\x9c\x0b\xa7\x8c\x37\xd8\x84\x65\xc7\xcb\x4e\xe9\x70\xd3\xae\xc8\xf5\x71\xca\x44\xae\x9f\x9d\x0a\x0b\x19\x51\xae\xdf\x77\x4e\xaf\x44\xe3\x4d\x1c\x49\xf7\x99\x08\xa2\x81\x70\x23\x29\x3e\x0e\x1b\x5c\x37\xbe\xc7\x91\x74\x5a\x56\xfd\x70\xe0\x35\x36\xd3\x73\x96\x40\x1d\xda\x72\x1a\x43\x1e\x8e\x31\x27\x5b\x43\x5f\x89\xc6\x30\x1a\x8f\xa3\x99\xcd\x28\xf5\x4d\x93\xdf\x15\x89\xa8\x81\x9a\xf1\xbb\xd8\x73\x7a\x35\xc5\xc6\x28\x33\xd8\xa0\x10\x66\xe4\x95\x86\x63\x8d\xd1\x37\x0b\xc9\x38\x13\x2c\xc2\xdb\x57\x12\xa6\x4a\x4d\x4c\xb5\x50\xe7\x98\xcb\x46\x28\x75\xd4\xe0\x2b\x5a\x80\xa9\xed\x64\xd4\x98\x46\x71\x1c\xfa\xe1\x38\xd4\xa1\x88\x9d\x96\x6d\xf4\xfa\xf6\x6d\x39\xc5\xf6\x6f\x80\x03\x1f\x61\xb6\xf9\x74\xe0\x43\x86\xe5\x3f\xa9\xc8\x1f\x8b\x89\xad\xc4\x34\x19\x37\x59\xd7\x61\x6d\x39\x9e\x69\x26\x6a\x70\xde\x72\xd9\x51\x78\x23\xa4\xc5\x80\x70\x0e\x6d\x91\xb7\x8a\xcc\xc8\x73\x0d\x7b\x80\x5d\x97\xbe\x0e\x8c\xe8\x7a\xa6\x37\x1c\xfe\x2d\x2f\x5a\x10\x78\x1a\x06\x78\x50\x1a\x5e\xe2\x81\xec\x17\x9a\xbd\x87\xcf\x6b\x45\xda\x0f\xa2\xe8\x83\x1f\xd6\x88\x7c\xaf\xd9\x0b\x4d\x66\xe4\xb3\x86\x1d\xd8\xdd\xa1\x14\xbe\x68\x76\x4b\x9e\x19\x61\xf7\x5e\xc3\x4b\xf3\x1f\x85\x27\x9a\x85\xf0\x63\xfd\x42\x8d\x47\x9f\x21\x5c\xab\x8c\xdb\xba\x3e\x69\x76\x04\x6f\x35\xfb\x02\xbf\xaf\x5e\xbb\xb2\x6c\xb2\xf0\xc7\xda\xaa\xb2\x9b\x16\xfa\x98\xbd\x1b\xa4\x60\x2f\x40\x09\xb6\x0d\x5a\xac\x76\x54\xf7\x32\x83\x7d\x46\x94\x80\xdd\x1d\x90\xd6\x8f\xe5\x83\xb6\xf3\x2b\xed\x4a\xed\xf2\x45\x96\x01\x4f\x14\xab\xd9\x6b\x14\x19\x76\x55\x41\x23\x5d\xfc\x55\x3d\x2f\x34\x51\x0f\x76\x77\x72\x39\x93\xfb\xbd\x0b\x02\x5c\xde\x93\x6c\x46\xb4\x40\x49\x97\x61\x4e\x96\x31\x63\xd2\x40\x91\x61\xde\xdd\xf9\x4d\xb9\x02\x04\x7b\x9b\x8e\xd8\xee\x0e\xe8\x76\x97\x52\x90\x4c\xf6\x0d\x0f\xba\x23\xea\x29\x77\x04\x06\xbb\x30\xd8\x4d\xe9\x5e\x7e\x7e\xfb\x99\x86\xdf\x0d\xd4\x90\xb6\x34\xcc\xc8\x1f\x18\x3a\xff\xdb\x7b\x4d\x11\xb2\xc8\xaa\x57\x86\x4c\xb9\x00\x3f\x53\xe0\x82\x3d\x87\x40\x6c\xd8\x89\x49\x17\x6d\x75\xd8\x29\xda\x9d\x08\xd8\xea\xc2\xfd\xc8\x13\x20\x3c\xfd\x60\x77\x67\xde\x81\xa1\x97\xa4\x2e\x16\xce\x52\xcd\xea\x8e\x3c\xc1\x36\xa1\x03\xa6\x67\x54\x4b\xc5\x54\xdb\x34\x92\x69\x10\x76\xb4\x38\x08\x0a\x09\x4b\xf0\xc4\xf2\xca\x0e\xeb\x1c\xca\xfc\x14\xe9\xbf\xef\xee\x80\x60\x88\x57\x83\x6c\xeb\xd2\xfe\xde\x0d\x09\x84\xa9\xa9\xad\x4d\x0d\x12\xce\xa0\x08\xf7\xf8\xa2\x0d\x37\x8b\x15\x3c\xba\x25\xdd\xed\x05\x0c\x05\xf3\x25\xf8\x82\xc5\x12\x62\xb1\x59\x81\x1b\x57\xbf\xaf\x58\xb8\x32\xce\xae\x05\x68\x75\x6b\x81\x59\x3b\xb9\xbc\xca\x6e\x37\x5b\x2c\x60\x20\x18\xd7\x70\x23\xd8\xe6\xb3\xf8\xf7\xfc\xc0\xe3\xe0\x07\x9e\x02\x9e\x78\x02\xfc\xc4\xd3\xe0\xdf\x79\x12\x82\x53\x0f\xfb\x72\x5b\x30\x2d\x61\x22\x36\xcf\xcb\x2b\xc1\xa4\x84\xa9\x58\x2b\x08\x0e\xbb\x7d\xe5\xdd\x91\x2b\xc3\x7b\x13\x7b\x4c\xd1\xb0\xcd\x48\x30\x2e\x61\xb6\xb1\x9c\xe3\xd8\x82\x1d\x48\x6f\x52\xb9\x13\x6b\x8e\x4f\x75\x30\x4e\xa6\xa2\xd6\x80\x60\x7b\xbb\x78\x58\x61\x6f\x9f\x31\xdd\xef\x7a\x1d\x48\x98\xe8\x25\x45\x68\x53\xab\x55\xc4\xdf\xd6\x12\xb4\x63\x50\x64\xba\x4d\x95\x9f\xe6\x3a\xd2\x3d\xc5\xba\x9d\xdf\x54\x8b\x97\xb6\x63\x12\xc6\x44\xff\x48\x7b\xd7\x9a\xd8\x9a\xda\xca\x53\x74\x01\xb7\xeb\xe6\x44\x38\x24\x81\xa9\x64\x3e\x9f\x91\x6d\x01\xce\xff\xe5\x40\x42\x4b\x75\x58\x8a\x66\x64\x24\xc0\xf1\xcc\x37\xa4\x26\x5d\xc7\x39\xae\xe3\x55\xe0\x80\x71\x3c\xf7\x79\x27\xc8\x8c\x4c\x05\x04\xad\x2e\x66\xeb\x49\xc5\x0d\x2f\x4c\xc7\x23\xdd\xe3\x2c\xf7\xb9\x5e\x6b\x32\x24\x37\x02\x75\xd9\x99\xb0\xd1\xc4\x3c\x3b\xdd\xb2\x58\x02\x4a\xe0\x48\xe7\x5f\x29\x5c\x8b\x95\xab\x91\x6d\x9d\xa8\x37\x28\x49\x1b\xf4\xc0\x01\xeb\x81\x4a\x4c\x83\x12\x96\x14\xf9\xb4\x6e\xc8\xad\xa5\x65\x6a\x38\x55\x50\xc4\x88\x94\x25\x65\x82\x52\x30\x83\x29\x4b\x66\x01\x47\x62\x85\xc1\x60\x29\xd1\x75\x4a\x44\x4a\x49\xdf\x01\xab\xfa\x09\x9b\x66\x54\x14\x94\xdc\x92\x6b\x53\xc5\xb5\xb6\xfd\x29\x5a\x5d\xd0\xd4\xd0\x83\xd4\x08\x74\xd8\x56\x41\x6d\xcf\x18\x52\x4e\x56\x8a\xa0\x40\x97\xf2\xc3\xa6\x84\xe8\x94\x90\x7f\xcb\x92\xe0\x1a\x93\xe9\x5e\x33\x5d\x10\x72\x47\x8e\xca\x84\xe8\x56\x17\x93\xa1\x21\x19\xba\xbc\xd5\x91\x02\x1e\xa5\x97\xd2\x9d\x0a\x26\x24\x3c\x17\xab\xf5\xe9\x53\x01\x78\xcd\x96\xf7\xe0\x81\x03\x92\xf6\x67\xe4\xc4\x4c\x32\xac\xe2\x21\x48\x4a\xbd\x02\x26\xae\x00\x75\x2d\xd0\x23\x04\x32\xea\xfe\xb7\xe5\x19\xd9\xeb\xd1\xce\x02\xbe\x0b\x76\x24\x41\x4a\xf6\x5d\x98\xc9\xf8\x74\x2d\xb3\x88\x22\x41\x8c\x40\x2e\x16\xf6\xf8\x09\xcf\xde\x5b\xee\x8e\x18\xb7\xef\x23\x3b\x5a\x11\xc2\x46\x25\x58\x0b\x51\x4a\x9a\x92\xc0\x0c\x43\xce\x66\x18\xd1\x85\x97\x29\xb8\x1c\xf6\x3b\x9d\x43\xdd\x47\x33\xc9\x90\xf1\x5a\x1b\x15\xd5\xbb\x25\x4f\x85\xf5\x9a\xb4\xba\xa8\x84\x16\x5d\xbb\x8c\x4a\xad\xf9\xaa\xea\xaf\xab\x17\x27\x5c\x8a\xf5\x5b\xed\x79\xfd\x1d\xcb\x45\x6f\x2a\x5c\x54\xbe\xea\xe5\x8e\x5c\x0a\x58\x1f\x07\xa4\xc1\x5e\x02\x96\x3b\x57\x28\xbc\x13\xec\xb9\x84\x0f\x62\x5d\xd0\xc8\x8c\xbc\x13\xab\x76\xd8\xbe\x0b\xa2\x30\xea\xc6\xa2\x79\x55\x21\x5f\x63\xf0\xd9\x6a\x14\xea\x57\x50\xcf\xd2\x7b\x7f\xe9\xc2\x4c\x61\x5b\xc5\x99\x60\xc7\x12\x5e\xaf\x5d\x14\x2e\x25\x41\x8c\x67\xc2\xb6\x91\xda\x5b\x06\x36\x78\x9a\x3e\xac\xac\xbe\xb3\x00\xa2\xd8\x8c\xbc\x11\xf0\x3a\x45\x05\xd8\xaf\xaf\x04\x89\x34\x85\xef\x82\x9c\x51\x48\xad\x52\xb1\xa1\x02\x64\xee\x05\x85\x63\xb9\xde\xbb\xf2\x41\xa4\xcb\x57\xef\xa3\x74\x4f\x79\x7c\xcd\xee\x7d\x4f\x4a\x08\x3c\x2e\x8d\x92\x2e\x41\x78\xc7\x12\x86\xf9\xb9\xe4\x22\xa8\x48\x94\xf4\x07\xfe\xce\xdb\xea\x82\xff\xdd\x73\x1c\xf0\xaf\x2b\xd9\x4e\x8f\x2b\x70\xc2\x9b\x46\xe0\x7f\xab\x40\x7c\xad\x40\x9c\x7a\xc7\x82\x38\x0e\x05\xfe\x35\x7b\xba\xf1\xee\xf9\x77\xef\x48\x03\xbf\x36\x7f\x83\x5b\x4f\x02\x9f\xe2\x0b\x85\x7f\x7f\xe2\xdf\x23\x9c\xf4\x71\x5e\xfe\x2c\x7b\xf2\x07\xe6\xbb\xff\x39\xfb\xfd\xc6\xdb\xea\x96\xb3\xf7\x95\xea\x27\x33\x72\x1b\xa1\xf8\x46\xa9\x72\x17\x41\x17\x24\xf5\x24\x6d\x39\x0f\xf8\x34\x7c\x70\xb3\x53\xba\x1f\xf0\x99\xd8\x98\x06\xf6\x65\xf5\xf3\x7e\xed\xf3\x0b\xb1\xca\xcd\x56\x64\x97\xab\x7e\xde\xad\x7d\x7e\x2f\x36\xe6\x98\xfd\x52\xfd\xbc\x57\xfb\xfc\x64\x73\xdd\x3f\x36\xd7\xfd\x69\x33\xf2\xb7\x9b\xdb\xfd\xfb\x66\xca\xff\xd8\xdc\xa9\x32\xd9\x48\xb9\x4a\x36\x96\xd6\xc9\x46\xca\x45\xb2\x91\xf2\x24\xd9\xd8\x2d\xbc\x46\x5a\xbd\x65\xc1\xe6\xe2\x51\x52\xde\x2b\x47\x23\xc3\xb6\x0e\x56\xae\x93\x9f\x23\x63\xa4\xcc\xc8\xef\x51\xea\xf6\xb4\x4e\xa1\x02\x5f\x98\x6c\xbe\xd9\xf8\x8e\xbc\x47\x14\x76\xff\xb8\x48\xef\x91\x54\x12\x8e\x3e\x89\xea\xfb\x92\x23\x32\x41\xb1\xa4\x69\xe6\xb3\xbb\x13\xa5\x3d\x69\xe5\x6e\xf7\xa3\x84\xfc\xe3\xb5\xb4\x17\x4b\x84\x52\x8b\x91\x50\x5e\xc3\xf9\x47\x4b\xb6\xfe\xe1\xfc\x83\x7a\x41\x88\xf1\x06\xd9\xf2\x13\x25\x24\xcd\xf6\x2d\x06\xd6\x35\xa3\x69\x8b\x38\x8d\x41\x38\x0a\x75\x0c\x98\x46\x7f\x14\x69\xfb\x09\xeb\x36\xb2\x0f\x92\x90\xe8\x90\x28\xdc\x91\x2c\x52\x92\x26\x65\xe3\xa7\x74\x13\x70\x42\x64\x71\xd0\x96\xe3\xc9\x0b\x1f\x02\xb6\x85\xca\x6e\x6f\x45\x2f\xd9\xa6\xdd\x90\x69\x08\x09\x48\x0c\x28\xf0\x5f\x82\x74\xf9\x09\x6e\x9b\xe0\x5e\x26\xc7\x1b\x9f\xec\xad\x8e\x41\x7e\x00\x8e\x68\x68\x77\x8d\xf4\xa8\x0c\x11\xa7\xd4\xc3\x2e\x0f\xa0\x03\xf7\xfc\x04\x1d\x21\x45\x6a\x04\xdf\x58\x38\x2f\x3d\x61\x46\xdc\xe5\x8b\xf2\x88\x8c\xcb\x8c\x31\x0a\xc9\x8c\x5c\x85\x36\x0b\xec\x23\xe4\x8f\x72\xfb\x07\x65\x58\xd3\xb1\xd9\x30\x0c\xf8\x9d\x67\x7b\xb0\xb2\x43\x77\x53\xee\x2f\x32\x23\xb3\x10\xf6\x40\xd2\xf9\x7c\x0b\x9f\xbb\x9d\x0e\x48\xf4\x22\x9a\x0f\xf8\xa3\x54\x78\xbb\x54\x98\x10\xd9\x66\x5d\xfa\x60\x6f\xde\xa1\x6d\x22\x1f\x74\x3b\x9d\x79\x87\xb6\x88\x7c\xb0\x87\x4f\xa5\xd4\x3a\x7f\xc9\x97\xd7\xa6\x79\x6f\x23\x8c\x7e\x2d\xb2\x6d\x24\x15\x98\xe7\x61\x65\x40\xfc\x9b\x72\x7e\xf8\xa4\x32\x53\x9e\x86\x70\x1a\x56\xb6\x16\x47\xc9\x2f\xee\x4b\xde\x91\x57\x21\x26\xe4\xb7\x57\x06\x18\xc3\x33\xaa\x60\x9a\x95\x31\xc9\xbe\xa3\x55\x22\x1c\xcf\x19\xf2\x71\x2c\x4a\x2b\xc5\x5d\x05\xcc\xdd\x9e\xcf\x1d\x67\x2b\xbd\x7f\xda\xac\x5a\xc5\xb1\xf0\x32\xe0\x67\x33\xd6\x97\x11\xbc\x0f\xe1\x54\x13\xd9\x72\x98\x53\x61\xf6\xeb\x64\xed\x0e\xa5\x73\xe9\xd8\x14\xd5\xb5\xad\xca\xa3\x0a\x21\xac\x60\xa5\xc7\x96\x95\xaa\x13\x83\xc9\x4a\xf8\xca\xbf\x60\x56\xcc\xe7\x9d\x43\x76\x47\x64\xb8\x4a\xa8\xe9\x0a\xed\x0b\xc0\xbb\x10\xfe\xcb\x13\xa9\x97\x47\x7d\x95\x32\xb4\x57\x39\xe4\x93\xe9\x04\xa7\x7c\x4f\xef\x69\xb2\x71\x91\x7a\xbe\x79\x99\xf9\x56\x9e\x18\xd2\xdd\xee\x9f\x26\xde\xf3\x84\xda\x1b\x1c\x8a\xd3\x82\x9b\xeb\x78\xba\xb9\x8e\xcb\x6a\x13\xd4\x10\x24\xc8\x61\x39\xe1\x7a\x15\x20\x1b\x68\x8b\xa7\x04\xf7\xae\x0c\x17\x27\xe4\x4d\x52\x15\x11\x1f\xca\xf3\xf5\x28\x24\xc7\xe4\x7c\x46\x06\x21\x04\x21\xf9\x9e\x90\x0e\xa5\xf0\x2e\x21\x27\x09\xee\x93\x00\x7e\xc9\x3e\x3f\xc5\x97\x70\x99\x90\xe5\xc1\x76\xfe\xfc\xd3\x8e\xf2\x3a\x80\xad\xce\x22\xc3\xf7\x0b\xa8\xec\x39\xc5\xfc\x1a\x60\x7a\x51\x6e\xc1\xab\xda\xec\x4b\x1d\x22\xd5\xd1\x38\xab\x02\x61\x48\x90\x4c\x63\xe9\x8b\x94\xe4\x35\xa0\xe2\xcb\xc7\xa4\xbc\x87\xe5\x7f\x2b\x42\xc7\x82\x57\x2d\x63\x20\x0f\xc1\x71\x60\x46\x3e\x87\x90\x68\x38\x4b\x8c\x14\x1f\x02\x4e\xef\xd7\x09\x7c\x32\x75\x7d\xa4\x14\x7e\x84\x66\x71\xc3\x65\xb2\xa5\xcc\x3f\x25\x45\xba\x5a\xc3\x4f\xf4\x2a\x7d\xc1\xdd\xa3\x13\xcc\x14\x76\x8a\x93\xf7\x18\x33\x8b\xbf\xc2\xfd\x01\xce\x41\x2e\x6f\x2b\x4d\x86\x39\x3d\x01\x4d\xe3\x0a\xb7\x8b\x7b\xce\x64\x39\x8d\x38\x9a\x21\x48\xe5\xc7\xc4\xfe\x7b\xad\xe1\x4b\x48\x9c\x61\x38\xd6\x42\x19\x79\x94\x6e\x2d\x45\x6c\x46\x5e\x84\xab\x75\x95\xdb\x24\x13\xa2\x74\x01\xaf\x88\x84\x63\x72\x7e\x49\x9c\x38\x1c\x0b\x19\x88\x81\x83\x3e\x84\xc4\x52\xb5\x85\xee\x0c\x33\xd6\xc4\x09\xe5\x55\xe8\x87\x7a\x19\x42\x64\x10\x93\x64\xc5\xd7\x24\xfb\xca\x03\x8d\x69\x9d\xca\x9f\x3b\x46\x80\xd8\xcf\x4a\x04\x22\xbc\x11\xca\x81\xbb\x94\xbd\x88\x33\x52\x51\x32\x75\x20\x32\x1c\x94\xeb\x05\x9d\x43\xdc\x2c\xea\x3b\xfd\x6c\x0f\xa5\x69\x40\x3c\xa7\x24\xe2\xbf\x26\xa9\x7e\xd4\xb6\xc7\xe7\xb6\xe7\xf3\xf4\x69\x50\x7a\x16\x45\x4f\xcb\x5e\x01\x2c\x2c\x90\x7d\xe0\xc5\x28\x0f\x70\x90\x05\x64\xdb\xd3\x1a\xd3\xc7\x6b\x4c\x1f\xaf\x5d\x51\x38\xa7\x2e\x43\x63\xa8\xa0\x3c\x0e\x00\x7f\xda\xe3\xcd\x18\x13\x82\xc9\x62\x04\xcd\xde\x67\x49\x46\xf3\x94\xd6\x58\x51\x98\x56\x14\x62\x45\xa1\x1b\x80\x66\x84\xb3\xd0\x1d\x50\x53\x9e\x71\x57\x40\xc0\xc2\x5a\xa5\x1d\xe0\xae\x0f\x3c\xab\x74\x89\x86\xc8\xf5\x21\x72\x03\x88\xdc\x01\x44\x86\x06\x4d\x33\x48\x43\x86\x42\x32\x0a\x4b\xec\xbf\xd2\x87\x83\xac\x0f\x07\xcb\x7d\x68\xba\x40\x60\x03\x13\xbc\x32\x97\x33\xe1\x06\x10\x30\x61\xc8\x62\x62\xa9\x27\x43\x5c\x05\x87\x6c\x45\x6f\x6a\x5c\xdd\x8a\xde\xcc\x12\x0c\xd8\xde\x2c\x17\x14\x8c\xe0\x75\x58\x14\xab\x25\x66\x5e\x09\x8a\x95\x4b\xac\x5c\x62\xe5\x72\xa9\x47\xb3\x60\x99\x94\x16\xa2\xcc\x80\xd3\x95\x83\xd9\x85\x10\x86\x20\x96\x68\x29\xf5\xe9\xb3\x25\x5d\xe7\xcb\x10\x26\x55\x2d\xe6\x65\x15\x66\xe2\xe7\x9b\xf4\x85\xb5\x5a\xd3\xa9\x7c\xb8\x0f\x84\x31\xfa\x83\x8f\xc6\x9a\xae\xc0\x7e\xae\xc2\x7e\x43\x2d\x21\x32\x0d\xc1\x7f\x8d\xda\x31\x1d\xc2\xa5\x0f\x2f\x12\xe2\x9c\xb7\xcf\xff\xfc\xf3\xe2\x7e\x41\xe8\x6f\xad\xbe\x0b\x7f\xfe\xf9\xe7\x9f\xff\x63\x7b\xfe\x6f\x7f\xfe\x19\x5f\x38\x94\xc2\x1d\x79\xe3\xa3\xdf\xf5\x32\x5a\x7d\x18\x27\x78\xbb\x30\xda\x91\x59\x04\xa8\x75\x8b\xd4\x0d\xa1\xf7\x75\xc9\xee\xdc\x67\xd3\x18\x30\x76\xed\x8d\x30\xd2\x4d\x52\xda\x72\x16\x4e\x65\x52\x7f\xd9\x6c\xb2\x3d\xa9\xad\xe0\xf5\x25\xfc\x47\xcd\x22\xac\xaf\xe1\x9f\xaa\xdf\x1f\xd7\x0d\xe9\xea\xe7\x47\x75\x43\xfa\xd7\xb5\xd8\x5b\x59\xd5\x62\xef\xab\x03\xf6\x47\x19\xd3\xef\x09\xb1\xe2\x59\xf2\x89\x70\xe0\xcc\x27\x66\xd4\xac\x74\xb4\x69\x9d\xd2\x77\xdf\x52\x21\x1d\x1f\x8b\x91\xb8\x75\xe0\xad\x59\x48\xfc\xab\xec\xed\xf3\x1f\x09\x1f\x9b\xee\x9d\x0e\xe1\x99\x6f\x97\xbe\xb7\x43\x43\xc3\x88\xd6\x16\x68\xc9\x57\x87\xc3\x29\x5e\x2c\x79\x33\xf2\xd2\x30\x42\x77\x6f\xaf\x43\x5b\x0f\xbb\x8f\xf7\x0e\x1e\x19\x09\xa5\x0e\x3b\x7d\xd5\xee\xee\x1d\x74\x1e\x1f\x78\x8a\x3e\xc0\xa7\x87\xf3\x8e\x99\xa5\xf6\xf5\xc3\xdf\xb4\x99\x7e\xa2\x4d\x04\x7e\x45\xb3\x44\x3c\xd8\x3d\xd8\xdf\xb1\xc6\x8a\x7d\xfd\xf8\x60\xde\xa1\xd4\xbc\x9e\x67\xd1\xb9\xf7\xfc\x77\x8f\x48\x26\xda\x64\xf7\x60\xff\xb7\xa4\x45\x92\xd4\xbc\x49\x52\xf3\x86\xd2\x36\x21\xdd\xfd\xdd\xdf\x88\x62\x64\xff\x37\xd9\xda\xa1\x0f\xba\xfb\xbb\xa6\x86\x1d\xfa\x60\xdf\xfc\xdb\x05\x3e\xf5\x04\x53\x2d\xa2\x0e\xbb\x9d\xfe\xae\xd7\x7e\x4c\xc1\xdf\xf5\x92\xd6\x5e\xa7\xf3\x9b\x6e\x91\x9d\x43\xd1\xef\x78\xdd\xb2\xa9\xa3\x79\x65\xfe\xc8\x18\xf6\x60\x46\x74\x0c\x22\x46\x2e\x25\x4e\xdb\x30\xb0\x8c\x61\x07\x56\x6d\xd6\xd5\xb7\xea\xba\xb5\xad\xba\x9d\xda\x56\xdd\x6e\x2d\x33\xc3\x5e\x2d\x8f\xc3\x7e\xed\x38\xfa\x41\xf5\xf6\xc3\xc6\xc3\xda\xcd\x83\x8f\x6a\x89\x00\x1e\xd7\xae\xca\xea\x76\xea\x57\x5f\x75\xbb\xf5\xdd\xc2\xee\xce\x62\x41\x66\xe4\x93\x9f\x36\xba\xda\xea\x19\x79\xef\x17\xbd\x71\x5a\x7a\xff\xa5\xf4\xde\x2b\xbd\xff\xb1\xe6\xbd\x2a\xf5\xaa\x9b\xbe\xdf\x85\x19\x79\x92\x57\x8c\xff\x6b\x39\xdf\x4a\x62\x41\xf0\x8a\x2a\x76\x65\x73\x98\x5a\x71\xef\x8f\xa8\x59\x86\x8a\x7d\x92\xfb\xe0\x95\x87\x72\xef\xa3\xb7\xa5\x9a\x4d\xbc\xdc\x7c\x3e\xd7\x7d\x7c\xde\xf1\x76\xbd\x2e\x3a\x44\x5d\xff\x5b\xd9\xd5\x54\x99\x11\x87\x9d\x54\x65\x1d\xc7\x64\xe5\x44\xaf\x07\x13\x49\x34\xc3\x54\x29\x36\xa8\x71\x49\xd4\x03\x31\xef\xf4\x65\x8b\x7c\xd3\xf6\x99\xb6\x88\x6e\x39\x0d\x87\x52\x0f\x77\xd9\x42\xbb\x7d\xb0\xc0\x09\xec\x00\x0f\x8d\x21\x00\x83\x98\xe2\x49\x8f\xc2\xcf\x55\xa2\x6d\x2b\x77\x19\x34\x9b\x5b\x65\x9f\x41\xe6\x41\xb0\x4e\x83\x92\x13\xac\xdc\x30\x33\xad\xac\xdf\xc0\xa8\xc8\x93\x18\x24\xec\xd1\x76\xfa\xd4\xed\x74\x68\x2b\x7b\xdb\xe9\x94\x29\x88\xf8\xff\x1f\xd9\xbd\xf0\xdc\x95\x9b\x87\x71\x0f\x5d\xc3\x89\xf7\xd5\x66\x75\x6a\xcd\xea\xd6\x9a\xb5\x53\x6b\xd6\x6e\xad\x59\x7b\xb5\x66\xed\xd7\x9a\x75\x50\x6b\xd6\xc3\x5a\xb3\x1e\xd5\x5b\xf5\xb8\x7e\x55\x5d\xb7\xb3\xd4\xcc\xb2\xdf\x7d\x58\x9a\x45\x44\xb0\x19\x99\xe1\xb0\xa3\xcc\xc6\xdb\x9a\xa4\x99\x51\xf8\xda\xe8\x6c\x28\xb0\xf1\xbd\xce\xc1\x8d\xaa\xd4\xdd\x3b\xe8\xe2\x6b\x51\x81\xcd\x95\x77\x23\x67\x55\xab\xdb\xe9\xfc\x26\x5b\x7b\xbf\xe9\x96\x70\x79\x8b\x08\xd7\xef\x77\xbd\xb2\x5b\xca\x2f\x53\xa3\x98\x21\x8e\x29\x26\x29\xdc\x73\xed\xc9\x76\xc0\x89\x42\xc1\xad\xca\x01\xd3\xa3\xd8\xe8\x85\xbb\xa8\x1e\x72\x5d\xc2\x16\x97\xd9\xfc\xd1\xc1\x9e\x40\x46\x7f\xd8\x7d\xdc\x3d\x28\xdf\x13\x33\xe6\x95\x25\xfc\x4d\x0c\xdd\x5d\x2b\x77\x4a\x2e\x3d\x5e\x8f\x09\xef\x4f\x34\x71\x4e\xae\xa2\x64\x3c\xc0\x1b\x7c\x7d\xd1\x10\x93\xa9\xbe\x73\xa8\x37\x23\xaf\x63\xd8\xd6\xc4\xf9\x5d\x45\x72\xd4\x78\x7d\xf2\xf1\xd1\x41\xa7\xdb\x18\x46\x6a\xc2\xb5\x43\x61\x5a\x33\xee\x6f\xca\x04\xbc\x23\xd7\x11\xdc\x1f\x1b\x41\xb3\xd5\xa1\x70\x92\x3d\x9c\x66\x0f\x5f\xb2\x87\x57\xe6\xe1\xbd\x31\xa9\xde\x08\x10\x1c\xe5\x64\xd9\xa7\xb0\x5d\x46\x1b\xa0\xdc\x92\x94\x6e\xa2\xbb\xea\xa6\x9a\x54\x04\x6c\xf0\x0a\xcd\xa0\x8f\x56\xb8\x7d\xab\x86\x4a\xa6\xd3\x44\xd7\xa5\xc0\x25\xd9\xea\xc2\x56\xa7\x9e\x1e\xd4\xbe\xee\xd6\xd3\x08\x5d\x92\xad\x0e\x42\xd7\x18\xd6\xbe\x37\xab\x33\xa1\x98\x97\x31\x97\xea\xfe\xc8\xf4\x41\xe2\xfa\x14\xfc\x2b\x4f\x82\x1f\x79\xca\x08\x72\x51\xf6\x59\x56\xd7\x89\x2c\xb7\x56\xea\xfb\xf3\xbf\x63\x87\x7c\x1a\x0b\x43\x4a\x10\x4d\xa6\x63\xa1\x45\x83\x0f\x06\xa1\x1c\x61\x08\x1e\x9e\x9e\x32\x56\xb6\xa7\x5c\xbf\x3f\xd3\xb6\xbf\x27\x78\x3f\xa8\x67\xca\xbe\xb7\x00\x71\x83\x2b\x81\x99\x32\x42\x25\x06\x65\x3f\xd6\xb4\xca\x60\xbf\x9b\x45\x4f\xc4\x70\x4b\x7e\xc4\xd0\xed\x1a\x2b\x2c\x06\xe4\xbb\x9d\x6c\xb9\x2b\x79\x49\x97\x99\xb3\x5b\x67\xce\x19\xdf\xb8\x1d\x73\x57\xed\x00\x6b\xce\xf2\xaf\x76\x20\x3f\xa3\xd7\x82\x9f\xa1\x41\x14\xa3\x41\x74\xd3\x2b\xb6\x01\x67\xe4\x6a\x0c\xdb\x46\x69\xe5\xa7\xb8\x1b\x98\xbd\x30\x26\xa4\x17\x40\x6c\x5f\xdc\x8c\x81\xe3\x66\x1f\xfe\xfa\x1c\x9b\xa9\xfd\x8d\x42\x82\xdb\x7e\x0a\xfc\xcf\xf6\xc3\x00\x23\xb1\x6a\x3b\x7f\xb7\xe5\x16\x1a\x2b\x92\x48\x86\x63\x46\xdd\xed\xfe\x64\xec\x99\xd6\x55\x9c\x44\xd7\x7c\xe3\xfe\xd1\xd1\xe6\xde\x38\x29\x57\x77\x35\x24\x47\xe3\xea\x64\x3c\xdd\x5c\xfc\x39\xdf\xec\x74\xdc\xfc\xf9\x7b\x45\xa3\xa8\x26\xd8\x29\x39\x1d\xab\x52\x10\x95\xf7\x33\xab\xbb\xcf\xc8\xe7\xb1\x8d\xb1\xc8\x6d\xb7\x3f\xff\xec\x5b\x0f\x90\xcb\x0f\x28\xa5\xae\xdf\xbf\xc4\x54\xf0\xca\xf5\xad\x03\x2d\x0b\x38\x55\xae\x8f\x31\x19\xd4\xbb\x24\xce\x03\x07\x8e\xf2\xf3\x47\x58\xc9\xf1\x18\x5e\x8c\xe1\x1d\x91\x70\xcf\x0f\x70\x2f\x37\xf1\x0c\x9e\xe0\xd4\x30\xfe\x82\xe2\x78\x7c\x8b\xcc\xbb\x92\x03\xb4\x44\x2a\x92\xdd\x5b\xca\x9c\x96\xad\x7d\x99\x6d\x66\xca\x57\x57\xc1\xd4\xac\x2a\x3e\xec\x78\x15\x73\xac\xf8\xb0\xeb\x95\x2f\xe9\x2f\x7f\xe9\x14\x5f\x0e\x2a\x1f\xf2\xa5\xf5\xc9\xb8\xb6\x96\x7e\x19\xd7\x16\xdb\x1f\xe3\xba\xe4\x79\x3f\x2e\x0d\xde\x1b\xbe\x71\x63\xf2\x1d\xdf\x6c\x87\x7e\xa8\x7e\x7f\x58\xfb\xfc\x8a\x6f\xb4\x33\xcf\xaa\x9f\x0f\x6a\x9f\x5f\x97\xc6\xe1\xa3\x2e\xed\x04\x76\xd3\x6b\x4d\xa4\x67\xcc\x23\x54\x49\xa9\x6b\x0c\xc1\x4f\x21\x44\x98\xd0\x99\x56\xef\xf5\xfd\x58\xb5\x7b\xf4\x00\x8e\xc9\xb9\x1c\x10\x87\x8f\x85\xd2\x0d\xfc\xdb\x9e\x71\x25\x43\x39\x72\xe8\x05\x35\x9f\x93\x01\x41\x02\xaa\x06\xe5\x71\x19\x93\x4a\x88\x36\x4b\x95\x3f\xc0\xb0\x4e\x54\xc7\x39\x7c\xf4\x3a\xa9\xde\xbd\xa8\x48\xbd\xaf\x55\x22\x06\x03\xc8\xee\x9d\x88\x45\x75\xba\xfe\xac\x42\xfe\x31\x06\xe7\x4a\x89\xa1\x03\x0f\xfe\xc7\x77\x7e\xc3\xed\xfd\x2f\xde\x83\xd0\xd5\x22\xd6\x84\x48\x26\x69\x7e\xda\xf3\xc1\x9f\xf1\x83\x11\x38\x0e\xa5\x98\x74\xb8\xec\xaf\xa9\x62\x7d\x23\xea\xfb\xaf\x25\x67\x6d\x62\x7b\xb1\xee\xb2\x9d\x62\xc7\x21\x79\x70\x3b\x20\xce\xa5\x3f\xe6\xf2\xba\xd4\x63\x12\x7b\x0b\x5e\x9b\x09\x3a\x1b\xc0\x1d\x26\x73\x3b\xab\x74\xc3\xcb\x8a\xe4\x36\xba\x98\x2c\x07\x30\x9d\x0c\xe0\x0c\x70\x27\xe0\x28\x1f\x25\x2d\x6e\x75\x5b\x46\x33\xc5\xa7\xa5\xba\x54\xcb\xf1\xcc\x4f\x0a\x33\x72\x9d\xc3\xce\xda\xdd\x4e\x07\xa1\x9e\x2d\x8f\xde\x0b\xbe\x29\x22\x6c\x3e\x5f\x19\x00\x36\xcd\x71\xfb\x5a\x36\x7c\x2d\xdb\x51\xa2\xc7\xa1\x14\xed\x50\x0e\xa3\x86\x1f\xa9\x81\x50\xed\x8e\x43\x01\x3b\xc6\xd2\x37\x23\x71\x5e\x6c\xc8\x1b\x43\xde\xc6\x12\xc1\x15\x57\xba\x31\x51\xed\x1d\x24\xf1\x8c\x42\x32\x20\xce\x49\x94\xa8\x40\x60\x5b\x3c\xf3\xbb\xbc\xce\x7e\xde\xdc\x5d\xba\x4c\x5c\x1b\x7d\xcc\x88\xbe\x31\xf1\xd3\x3a\x90\x18\xb1\xd4\x86\x78\x92\x51\xae\xc2\xd1\x95\x6e\x77\x1a\xd8\xcb\xd6\xed\x6d\xba\xf4\x66\x00\x4e\x12\x0b\xd5\x8e\xc5\x58\x04\xda\x01\x27\x94\xa1\x0e\xf9\x38\xff\xda\x9e\x44\x3f\xdb\x7f\x01\x32\x13\xfe\x75\xa8\xff\x02\x2a\x25\x24\x88\xc6\x91\x72\xc0\xf9\xb7\x20\x08\x2a\xe3\xfc\x0f\x96\x6f\xf1\xdb\xe1\x1e\xae\x6c\xce\xa8\x3d\xe4\x03\x31\xa8\x0c\x51\x2c\x82\x48\x0e\xb8\xba\x73\x28\x7c\xe5\xe4\x98\x93\x4b\x8c\x02\xa3\x14\x26\x03\xe2\xbc\xc0\xcd\x86\x86\x7f\xd7\xd0\x57\x61\xdc\x18\x73\x5f\x8c\x4b\x55\x3b\x2d\x1c\x94\x0a\x0f\xbd\x2f\x6b\xcd\xff\xf6\x20\xdd\x6a\x88\x1f\x48\x31\xeb\xdb\xbd\x0b\xe6\xb4\xde\x87\xe4\x7d\x4d\x21\xfe\x52\x1a\xc8\xb3\x84\x48\xd7\x3f\x71\xfd\x8f\x95\xe8\x86\xbf\xc9\x6b\xef\x39\x59\x9a\xc6\xb9\x52\xf5\xc4\x6e\x2f\x77\xd2\xbd\x11\x5f\x9b\x1a\x71\x0f\x68\x1d\x83\xfa\x62\x3c\x6e\xc7\x63\x1e\x5f\xb5\xa3\x65\x16\xb5\xcd\xb4\x3c\x6a\xcf\x02\xc1\x26\x72\x07\x5c\x8e\x4c\xc7\x56\x08\x2e\x77\x97\xd3\x52\xbf\x40\xc9\x3a\x3a\x06\x48\x48\xa9\x77\x9f\x54\x67\xf6\xf7\x41\xed\xcc\xef\x8f\xea\x77\x51\x5a\x01\xc2\x91\x34\xac\x39\x6c\x07\x42\x1a\x66\xc8\xab\xb4\x3c\x70\x69\x44\xa1\xff\xb9\xc6\x05\x9f\x56\x08\xf3\x2b\xd3\x66\x07\xf0\xb6\x2c\x09\xc7\x83\x32\xfc\xdb\xcd\x1a\xd8\xef\x7c\xa3\x3b\xf8\x8f\xd5\x56\x8b\x2c\x6f\x08\xa6\x76\xc3\x96\x9e\xcf\xf1\xe4\x2c\x5a\x0f\x3b\x36\x71\x3d\xde\xb0\x94\x1b\x12\x95\xa8\xa7\xa0\xd4\x8e\x55\x0c\x55\xf1\x45\x49\xd7\x1f\xa5\x2e\x29\x5d\xf5\x45\x65\x1c\xe7\x47\xb0\xce\x17\x85\x8e\xdd\x45\x35\xd0\x43\x95\xab\xbf\x24\x12\xd3\x7b\x14\xee\xca\xa0\xba\x99\x3e\x30\xa2\x63\x9a\xe8\xb4\x8f\x55\x90\xf5\xf5\xdb\x41\x85\x19\x44\xb0\x34\x38\xd7\xe2\x6e\x10\xcd\x64\x3e\x3a\xbf\x57\x46\x27\x59\x59\x20\x99\xae\x01\xe7\xc1\x1a\x75\x22\x88\xc6\x8d\x20\x1a\xb7\x79\xa2\xa3\x42\xf8\xfe\xa2\x8c\x1e\x6e\x9c\xfb\x56\x7e\xcd\xc8\xcb\x01\x6c\x61\xb4\x4c\xce\xa0\xb8\x41\xbc\x56\x30\x56\x27\x64\x19\x4b\xb7\x82\xc5\xf9\x7f\xfe\xef\x4c\xd6\x55\x18\x3d\x08\x36\x6a\x78\x51\xb0\x51\x7f\x0c\x97\x3b\x76\x12\x25\xb1\xc0\x99\xb6\xac\xf8\x0c\xd7\x80\x8f\x05\xbf\x11\xcb\xe0\x7e\xb0\x51\x7f\x8c\x83\x8d\x36\xd5\x38\xd8\x38\xe7\x06\xc1\xc6\x19\x7b\xb3\x4c\xaa\x3f\x4e\x56\xb4\x69\xfb\x7f\x23\xb3\x04\x37\x75\x66\x91\x7f\x93\x51\x0c\x86\x5f\x63\x94\xc9\xe6\xee\xbc\xda\xcc\x28\xd3\xcd\x63\x35\x0a\x36\x46\xb4\xcc\x36\x33\xc2\xdd\x66\xe4\xb7\xc1\x46\xfb\xf6\xba\x56\x77\xfd\xfb\x51\xf0\xbf\xd6\x67\x5c\x33\xe7\x1e\x96\xfd\x00\x41\xdd\xb1\xb2\x53\xf7\xab\x9c\xae\x63\xc7\x01\xd7\xa2\xa2\x03\xd6\x94\xfa\xc2\x5b\x10\xe4\xeb\x02\x1e\x1d\x9c\x0e\x61\x18\x92\x0e\x1a\xeb\x53\xba\x4a\x35\x0d\xf8\x58\x18\x25\xec\xb2\x31\x89\xa4\xbe\xca\x50\x13\xc5\x34\x94\xe1\x54\x34\xb3\x10\xed\x2b\xcc\x7e\xb4\x6a\x56\x4c\x95\xb8\x69\x23\x50\x63\xd0\x1e\x8e\xc5\x6d\xba\x6c\x5b\x86\xfd\x79\x93\x17\x79\x79\x93\x2f\xf1\x4a\x45\x33\x67\xad\xb6\xc1\xe5\x68\x2c\xda\x63\x31\xd4\xe6\xd7\xee\x6d\x23\x48\x54\x1c\xa9\xf6\x34\x0a\x2d\x62\xd4\x3e\x2e\x32\x11\x5b\x90\x62\x49\x35\x5d\x56\x27\x25\xef\xba\x6f\xc6\x10\xb2\xfb\x6b\x69\x14\xd3\xb3\x1b\x38\x4b\x95\x99\x5f\xd8\x61\x73\xde\x70\x99\x18\xed\xb5\xca\x45\xce\x0b\xe1\xab\xd2\xfb\x8c\x9b\x9c\xf7\x5c\x05\x57\x4e\x95\xa5\x9c\xa3\xa9\x0a\xc7\x4e\x95\xaf\x9c\xf7\x3c\x2b\xbc\x9f\xd7\x95\x48\xe1\x54\x1d\x0c\xce\x9b\x64\x9c\xc1\x3d\xcc\xf1\x25\xa3\x24\xd6\x4e\xd5\xf3\xe0\x9c\x88\xa9\x16\x13\x5f\x28\xa7\xea\xce\x77\x3e\x06\x3a\x2a\x5e\xe7\x5e\x7d\xe7\x43\x74\x93\xc2\x57\x39\xda\x79\x26\x02\xfb\xa1\xb4\x51\xa7\xe8\x72\xff\x4b\x64\xd6\x75\xac\xf0\xf5\x3f\xcd\x0a\x68\x10\xfd\x35\x2f\x5c\xd8\x01\x3d\xbe\xc1\xac\x1e\x95\x29\xf2\xad\x3a\xc9\x42\x05\xce\x84\xdf\xda\xf3\x77\x0e\xd4\x43\x65\xbf\x07\x15\x07\xda\x9b\x3e\x36\xf2\xac\xce\xf9\x93\x68\xc0\xc7\x0d\x63\xe2\x34\xe2\x2b\xd3\x8a\xd4\x7a\x1a\x84\xf1\x74\xcc\xef\x1c\xb3\x00\x45\xc1\xf5\xaa\x49\x83\x45\xdb\x83\x90\x8f\xa3\x51\xa3\xfc\x23\xed\xb1\x62\xba\x2f\x97\x0a\x6c\x02\xb2\xf5\x00\xf5\xb9\x5a\x2c\x2d\xc1\x38\x8a\x45\x63\x92\x2d\x71\x66\x54\x6e\x03\xf2\xfc\xa6\xbc\x9a\xdc\x3a\xab\xa7\x96\xc1\x6c\x73\x41\x67\x78\x83\x01\x5c\x07\x80\xd1\x2e\x37\x15\x60\x34\xf9\x1b\x86\x4e\x1e\xca\x82\x12\x94\x53\x15\xc0\xa9\x6e\xef\x35\x8c\x90\xf9\x9e\xc4\x3a\x1c\xde\x65\x6d\xab\xcd\xdb\x19\x79\x62\xc6\xb4\x63\x0a\xe3\x53\x37\x1b\xee\x35\x74\x0e\xa3\x48\xaf\xee\x81\xc9\xb8\xbd\xd3\xa8\xaf\xb0\x71\x12\x04\x22\x8e\xcd\xb2\xbe\xa1\x63\x9e\x72\x19\x58\x63\xb4\xba\x5e\x57\x50\x4e\x55\x38\xc9\x8d\xdb\xdb\x80\x7c\xab\xa0\x38\x11\xba\xf1\x8c\x6b\xf1\xe0\x34\x9c\x88\xd2\xa2\xbd\xbe\xc3\x79\x70\x3d\x50\xd1\xb4\xcc\x65\x19\xc7\x7b\x19\xb8\xe5\xba\x60\x1c\x4e\x1d\x70\x94\x08\x34\xe9\xe0\xa5\x17\x1d\x9a\xb3\xe4\x34\x8a\x43\xbc\x10\x13\x9c\x61\x78\xbb\x81\xbb\xb0\xa2\xcc\xbe\xfb\x0b\x7a\x0a\x52\x4a\x5e\xe5\xcd\x2b\xfb\xe5\x66\x1d\xee\xcd\x66\xad\xe2\xdd\x66\xbd\xe0\xc3\xf2\x24\x57\xd1\x2c\x5e\x9e\xdf\xaf\x36\xe3\x39\x0b\xca\xb1\x28\xdf\x35\x1e\x12\x3a\x26\xe7\x25\x6b\xd9\x01\xdc\xe3\x70\xc4\x20\xd4\x8e\x19\x3a\x74\xa0\xff\x1d\x5f\x81\x2a\xb1\xc5\x73\x83\xc5\xf4\x63\x11\x4a\xea\x9f\xb8\xfe\x71\x5f\x79\x7f\x13\xeb\x8c\xcc\xb6\x0d\x69\xd7\x76\x2f\xa5\x54\xc7\xb1\xb0\x37\x2d\x38\xd5\xf1\x7a\x5d\x6a\x2b\x06\x36\xa8\x22\xb0\x41\x95\x3d\x8d\xdf\x35\x6c\x19\xa3\xb3\xd9\x54\x7d\x87\x39\x9e\x79\x9e\xcf\x55\xbf\x78\xf7\x1f\x8e\xe7\x6c\xe1\x1f\x86\xdd\x65\x23\xc0\x5c\xff\x5b\xa5\xc2\x8f\x9b\x2b\x04\xc5\x3e\x0b\x72\xcd\x6b\x4e\x5c\x1b\x53\x91\xd5\xd5\x59\xaa\xbd\x1a\x5c\x51\x8a\xe7\x9c\x91\x1f\x37\x70\x8d\x89\x94\xb1\xa9\x65\xcf\x71\x90\xba\x59\xab\x39\x57\x1a\xff\xe7\x4c\xab\x22\xf9\x8b\xeb\xff\xb0\x1b\x6a\x6e\x60\x03\x3f\xb8\xcb\xf7\xd0\xdd\xc0\xdd\xe0\xa0\xa2\xe2\xfd\x7f\x76\x99\xba\xdb\xae\x7e\xc7\x9b\x03\x9c\x4d\x96\x12\x2e\x67\x56\xd4\xaa\x95\xf6\xd0\x5f\x2c\x61\xfa\x57\x56\x0f\xf1\x5f\x10\xd1\xa5\xbd\x86\xcd\xd6\xd6\xcf\x55\x26\x4b\xae\x5c\xa6\xc1\xcd\x35\xd5\x72\x2a\xe4\x20\x94\xa3\x25\x6d\x4d\xdc\x4e\x71\x6f\xb8\x84\xfe\x59\x55\x32\x3e\x5f\xc1\x25\xc5\x38\x7c\xdf\xae\xbf\x33\x9d\xfa\x81\x4f\x84\xd7\xb0\xab\x1f\x6e\x46\xf8\xd1\x52\x87\xfc\x15\x8e\xa3\xc1\x40\x89\x38\xae\xa0\xe1\xaf\x96\x0c\xd7\x97\x41\xc5\xcf\x15\x59\x3f\xd7\x89\xdd\x4a\x8e\x7b\x65\x9f\x61\xda\x8c\x37\xdb\xf6\x09\x97\xe9\x71\x12\x6b\xa1\x1a\x27\x98\x2c\xd7\xd6\x54\x0a\x22\xc0\xc4\x25\xe5\x6d\x15\xc7\xb1\xf3\x0c\x77\xad\x56\x19\x4b\xc3\x48\x4d\x52\xbb\xbf\xa2\xab\x16\x6d\x0c\xa2\x71\x3b\x9e\x54\x9c\x94\xb6\xbf\x9c\xa5\x2e\x4a\x41\xbb\x9d\x3a\x63\x9b\x1e\x20\x55\xd8\xff\x5c\xc5\xb6\xdd\xbf\x52\x75\xe6\x75\x25\x92\xd9\x30\x50\x9f\x0f\x46\xc2\x81\xad\x4e\xa5\xc7\xd6\x87\x5d\xd8\x02\x99\xfa\xe4\xac\x8c\xc1\x48\x61\xb2\xbd\xbc\xd5\x91\x17\x29\x50\xea\xe9\x40\x9f\xe3\x82\x18\x2a\xe5\x20\xdd\x58\xce\xa2\x77\x13\x63\xa0\x5e\x0d\xe1\x75\x92\x46\xec\xe5\x0d\xff\x15\xe3\x4d\x09\x3e\x58\x32\xdd\x62\xa1\xcd\x7a\xba\x3c\x91\x06\x61\xcc\xfd\x31\xce\x24\xa2\xcb\x42\xa0\xca\x4e\x62\x0d\x3b\x89\x7f\x25\x3b\x7d\x12\x42\x15\x83\x7a\xb5\x66\x50\xb1\x8b\x9e\x05\x20\x33\x7e\xaa\x6e\xb6\x2d\x79\x1a\xd2\xe9\x33\xbb\x29\xa6\x4f\x79\xda\xfc\xd7\xc9\xfe\x32\xd5\xe1\x2f\xcf\x83\x0f\xb1\x11\x2b\x7f\xe4\xdd\x6c\xe4\x80\xcb\x8f\x69\x1a\x4e\xbe\x0d\xeb\xa6\xfc\x57\xa1\x62\x54\x66\xa4\x8d\x7e\x32\x2b\xf2\xbf\xa8\x01\x4f\x14\x97\xc1\xd5\x2f\x36\x40\xb9\xfc\xc3\xaa\x85\xe2\x3f\x59\x75\x12\x8e\x07\xc6\x5a\xf8\xf5\xda\x3f\xfe\x8b\x6b\xff\x12\x0b\xf5\xeb\xb5\x7f\xfa\xd7\xd5\xfe\x32\x4a\xc7\xf4\xd7\x6b\x7f\xfc\xaf\xab\xfd\x58\xdc\x84\x7f\xab\x72\xff\xc5\xbf\xae\xf2\xbf\xdb\x70\xff\xb2\xec\xfe\x40\x6b\x9c\x7f\x71\x7d\x05\xe5\x19\x5e\x59\x20\x23\x39\x0c\x47\x19\xfa\x0f\x39\x31\xd3\xf6\x5e\xb1\x01\xcc\x83\x6b\x43\xb9\x1c\x38\xe0\xfc\xdb\xf0\xe1\xf0\xe1\xf0\x71\xfe\x71\x18\x49\xdd\x1e\xf2\x49\x38\x36\xca\xe3\x24\x92\x51\x3c\xe5\x81\x28\x1a\xf8\xae\xa8\x4d\x96\x88\xbb\x58\x3e\xb0\xf1\xb9\xec\xba\xb4\xc7\x95\x98\x74\x83\xb3\x2c\xc0\x87\xe7\x01\x3e\x79\x40\x0d\xfa\x1d\xde\x70\xc0\x33\xab\xc1\x37\x58\xad\xf4\xca\xa8\x3d\x4a\xb4\x16\x2a\x2e\xc8\xfa\x88\x5f\xaf\x6f\x88\x33\x0c\xc5\x78\x10\x0b\x5d\xee\xf7\x17\xa1\x8a\x75\x63\xc0\xef\x1a\xd1\x10\x43\xf2\x66\x42\x5c\xe7\xa3\x70\x8b\x1e\xab\xf7\x83\xe5\xb2\x77\xe4\xe8\x06\x9c\xf7\x91\x1c\x18\x5d\x7a\x2b\x71\x83\x5b\xe0\x9a\x82\x7d\x7f\x92\xd8\xf7\x5d\x7b\x4f\x1d\x7e\xb2\x18\xe5\x4d\x85\x4f\xd0\x6b\xb9\xd2\xdb\xeb\x7c\x88\xb4\xf0\x1a\xa7\x57\x61\xdc\x30\x6b\x55\x28\x47\x0d\xf3\xc8\x6f\x6c\xc2\xc3\x71\x14\xf0\x71\x23\xd6\x91\xe2\x23\x61\x88\xbf\x8b\x12\xd5\xf0\x8d\xe9\x6b\xb5\xd8\xdc\x59\x52\x8b\x55\x9a\x91\x70\x00\x2f\x02\xb0\xd6\xe6\x69\xfd\x2a\xba\x95\x9b\x8e\xef\xad\x19\xf2\xc6\x1a\x21\xcf\x30\xae\xcf\x7f\xbb\x1c\x8f\xb5\xeb\xd9\xf4\x51\xaa\x9c\xcd\xe8\x72\x1b\x04\x68\xe0\xb0\xb5\x95\xe4\x37\xbf\x57\x15\x06\x3e\xa8\x6b\x07\x1f\xb9\x4d\x21\xb0\x20\xd2\x0d\xba\xf5\x0b\xe3\x67\x64\x74\x63\x1a\xb0\x0f\xdc\xe5\xf5\x5b\x29\xb5\xb5\x2e\x83\x0e\x75\xf9\xb6\x3d\xaa\xfc\x15\xf0\xc6\xb4\x3b\x1b\x31\xff\x76\x0d\xf7\x4c\x7c\x33\x17\xaa\x7c\x93\xbe\xdf\x71\x28\x58\x16\x1a\x6b\xa1\xda\x3e\x57\xed\x3c\x76\xb3\xcc\x4c\xe3\xd4\x84\x30\x43\x1d\x0c\xd2\x03\x95\x1c\x3e\x0b\x9c\xd3\x37\x70\x1f\x5c\xe2\x69\x2a\xab\x58\xc0\x1d\xb9\xd9\x86\xd3\x6d\xcc\xcc\x05\xb7\x64\x7b\x1b\xae\xb7\xc1\xde\x97\x7b\x41\x69\x6d\x4b\x02\x31\xbe\x10\x70\x4b\x06\xdb\x70\xa4\x31\x9f\x90\x74\x03\x63\xf4\x07\xdb\xb4\x1e\xf0\x5a\x81\xbe\xd6\x84\x63\x34\xd6\x00\x1c\xa7\x02\xff\x70\xfd\x10\xdc\xdd\x94\xd3\x91\x54\xb5\x88\x57\xb9\xfc\x90\xfc\xc6\x37\x8a\x0f\xfe\xd3\xd6\xd1\x68\x34\x16\x46\x7f\x6a\x4f\x06\xd9\xcb\x31\x3a\x72\xf3\xb8\x90\x89\xdf\xde\x6f\x4c\x75\x7b\xb7\x31\xf5\xdb\xbb\xf5\xe8\x13\x3f\xd2\x3a\x9a\x38\xe0\x74\xa7\xb7\x8d\x38\x1a\x87\x83\x86\x1a\xf9\x9c\x74\xa0\x61\xff\x73\xbb\x3b\xfb\xb4\x18\xa6\xb3\x92\x58\xad\x79\x1e\xcb\x5e\x94\x94\x14\x5f\x71\x39\xc8\xa2\x20\x2a\x46\xca\x58\x28\x3d\xe1\x92\x8f\x8a\x01\xbc\xaa\x97\x96\xfc\xa6\x50\xb8\x5e\x6e\x13\x49\xe1\xc5\x36\x5d\xa5\x36\x17\xf9\xf4\x76\xbc\xea\x28\xa6\xca\x62\xad\xaf\x97\x16\x90\x50\x8e\x43\x59\x72\xda\x2e\xb7\x68\xcd\x86\x63\x2d\xbe\x43\x8a\x59\x45\xa8\x88\x59\xa3\x1c\x43\x62\x34\x45\xab\x30\x56\x74\xc6\x2f\x35\x8f\x5c\x7d\xbb\xf9\x49\xed\x7b\xfd\x60\xdb\x8f\xda\xf7\x7a\xc4\xe1\xa7\x32\x37\xfd\x21\xc9\x50\x55\x9d\x34\x6f\x83\x4a\x1a\xa7\xca\x64\x4d\x9f\xbe\x6c\x03\x86\x1c\x06\xaf\x69\xcb\x19\x87\xfe\x03\x3f\x8a\x74\xac\x15\x9f\xb6\xf7\xdc\x8e\xdb\x69\xf3\xf1\xf4\x8a\xbb\x07\xed\x41\x18\xeb\x07\x41\x1c\x17\x00\xee\x24\x94\x6e\x60\x4c\x97\x2f\x81\x19\xcc\x2f\xdb\x20\x2d\x0e\x5c\xe3\xf8\x4c\xc4\xd1\x44\xb4\xf7\xdc\x87\x6e\x07\x4b\x96\x5f\x17\x85\x7f\xd4\x0a\x8b\xf1\xa4\x3d\xe0\x5a\x4c\xc3\xe0\x5a\x28\x2c\x58\x7d\x65\x8b\x3d\x09\xea\xd6\x84\x35\x1c\xde\x10\xe5\x06\x78\x06\xf4\xce\xfc\x91\xb4\x97\x67\x17\xbe\x57\xf9\x93\x5e\xca\x38\xcc\x4b\xd2\x37\x7f\xe9\xaf\x7a\x19\x94\x5e\x2e\xf5\xed\xfb\xc0\xd4\x7f\x56\xd7\x3d\xd2\x29\x65\xa6\x6a\x2e\x1b\x3f\x07\xe8\x78\x29\x44\xd4\x8e\x87\xd7\x39\x34\x54\xce\xd6\xf6\xb7\x5e\x54\x3e\xcb\xfc\x73\x38\x24\x3b\xe8\x7e\x33\x24\x65\x65\x6b\x65\x8a\x44\x38\xdb\x36\x93\xbd\x91\xf4\x4b\x08\xfc\x1c\x01\x1e\x15\x5e\x8f\xb5\x32\xfd\x16\x75\xe4\x41\x29\x5d\x4d\xfe\xd2\xc7\x2b\x63\x72\x05\xc6\xa6\xea\xff\x3d\x80\x3f\x02\x90\x11\xa8\x08\x74\x04\x22\x82\x24\x02\x1e\x41\x10\xb1\xaf\x92\x38\xa7\x3c\xbe\x76\x28\x44\xd1\xba\x94\x5c\x41\x44\xf2\xac\x5c\x69\xf2\xae\xfa\x1d\x54\xc8\xd6\x9f\x71\xc9\x0a\x8e\xa1\x72\x33\x1e\x5e\x0f\x43\x3e\x28\xbc\xe5\x2e\x3f\xf9\xa5\xc8\x3d\xbf\x2d\x2e\x92\x11\xa5\x3b\xd4\x38\x13\xf0\x5a\xad\xba\xb0\x2a\x9a\xc6\x9a\x6b\xe1\x80\xa6\xf0\x1f\xaf\x95\x2b\xf9\x4d\x38\xe2\x3a\x52\x6e\x12\x0b\x75\x34\x12\x52\x17\x97\x27\x9d\xaa\x70\x80\x6e\xbd\x66\x73\x25\xb6\x2b\x1e\x5f\x65\x81\x57\x9a\xae\x3e\xbe\xd6\x53\x6e\xa0\xd5\xf8\xad\xb8\x9b\xcf\x95\x3b\x11\x9a\xa7\x8f\xf1\x55\x38\xd4\xf8\xdc\x3d\x34\xeb\x73\xa2\x75\x24\xe7\x73\xe9\x6a\xae\x46\x42\xe3\x91\xef\x68\x26\xc7\x11\x1f\xcc\xe7\x44\xb9\x53\x85\xd7\x3b\x3f\xb3\xbc\x40\x28\x2a\x27\x57\x4a\x0c\x41\x31\xd3\x35\x20\xd9\x73\x41\x34\x1e\x19\x22\x09\x91\xcd\xa6\x72\xfd\x3b\xcb\x2e\x77\xf8\x23\xb0\x3f\x02\xfc\x91\xb8\xdc\xfe\x4c\x5c\xde\xcf\x37\x06\xbc\x74\x27\x42\x2f\xec\xd1\x17\x08\x9e\x79\x2b\x23\xfc\xf0\xb2\x56\x09\x58\xb1\xa6\x0b\x18\xf8\x9e\xbd\x8c\xf5\xb1\x87\x57\xb8\x06\x7b\xe6\xdf\x3d\x83\x22\x8c\xd2\xe4\xf9\x43\x7c\xd8\x5d\x80\x1f\xb1\x81\x84\x38\x62\x81\x84\x31\xbe\xec\x2c\xe0\x06\x1f\xda\x3b\x0b\xd8\x8e\xd8\x4d\x04\x93\x88\x6d\x47\x70\xb5\x8e\xa5\xee\xf9\x73\x6f\x12\x01\x7f\x81\x81\xf5\xaf\xbd\x71\x04\xfc\x8d\xf9\x1b\xfc\xf0\x14\xf0\x6d\xef\x23\x26\x94\xf3\xb9\x97\xa6\x71\xe3\x97\x9e\xe3\x40\x70\xe3\x9d\x01\xdf\xc5\x23\xde\xaf\x3c\x09\xc1\x1b\x83\xc5\x1f\x7b\x67\xe0\x4f\x30\x9f\xda\x73\x54\x55\xf0\xa3\x7f\xe4\xdd\xa7\xc5\xf0\x27\x42\x3d\x31\x7f\x9e\x63\x62\xb8\x37\x58\xe0\x1d\x16\xf0\xbf\x7a\x1d\xbc\xe1\x20\x6b\xcf\x68\x3d\xe5\xcf\x90\x66\xa4\x36\x27\x94\x77\xbc\x69\x04\xc1\xad\x21\x7e\xdf\xfb\x8a\x59\x5b\x6d\xad\x1f\xbc\x71\x84\x37\x1d\x44\xec\xde\x3f\x35\x3f\xe0\x2e\xfa\x85\xdc\xaf\x1d\x68\xa7\x39\x5c\x6f\x23\x96\x48\xb8\x8e\xd8\x3d\xbf\xc2\xae\xe0\x48\x38\xe6\x97\x3b\x36\x7f\x4e\xcc\x9f\x53\xf3\xe7\x8b\xf9\xf3\x0a\x53\xce\x1d\x61\x4b\x0e\x16\x70\x82\x0f\x3b\x0b\x38\xcd\x06\xf0\x79\xb4\xfe\x76\x86\x83\xf2\xed\x0c\xdf\xb2\xb1\xff\x8e\x0f\x8f\x16\xf0\x34\xc3\x7a\x19\x6d\xb8\x86\x91\x48\xa2\x51\x50\xbc\x89\xd8\xca\x1c\x87\xcb\x97\xaf\x4a\x7a\xaf\xd5\xdd\xfd\x6b\x95\xdf\x35\xcb\x54\x71\xc5\x53\xf9\x0a\x5a\x25\xcc\xa4\x22\x78\xfe\x89\xd2\x05\xbc\x8b\xd8\x33\x09\x1f\x22\xf6\x53\xc2\xab\x88\x7d\x88\xcc\x78\x9c\x45\xec\x95\x82\xd7\xeb\x89\xbc\xe7\x6f\x3c\x0d\x7e\x68\x1a\xfb\xd3\xb6\xf6\xe3\xda\x61\x51\xae\xdf\xc7\x6c\x87\x91\xcd\xc0\x88\x49\x89\x8e\xd7\x83\xdb\x44\x89\x32\x4f\x92\xf8\x31\x82\x33\x3b\x96\xcf\x24\x8b\x56\x66\x19\x86\x00\x22\x08\x0b\xea\xde\x7a\x1a\xf8\x99\x17\x01\xef\x7a\x09\xf0\x87\x9e\x4a\x89\x7d\xe2\x09\xf0\x3f\x7b\x1c\xfc\x13\x2f\x04\xff\xcc\xc3\x44\xe7\xaf\xd4\xa6\x44\xe7\xbe\x30\x6d\x95\xa6\xe4\x47\x83\xe8\xd8\x28\x36\x14\xbe\x46\xab\xd3\x2e\x3f\x04\x1f\xd3\x2e\xff\x8c\x98\x2f\x48\x48\x21\xdc\x94\x30\xf2\x67\x04\x33\x12\xdb\x84\x6f\x36\x15\xe7\xb3\x88\x0d\x25\xbc\x8c\x36\xdf\x3a\x32\x94\x6c\x46\x9e\x45\x1b\x0e\x8b\x3b\x89\x9c\xaa\x28\x10\x71\x2c\x06\x4e\xb6\xb6\xc6\x82\xa4\xbe\xdb\x6c\xb3\xa1\xf4\x25\x35\xba\x9c\x38\x99\x4e\xd5\x52\xb9\x9d\x25\x15\xf6\x65\x44\x9c\x2f\xf2\x5a\x46\x33\xd9\xd0\x77\x53\xe1\x35\x9c\x96\xa4\x0b\x33\x7b\xb0\x4f\xef\x48\x08\x36\x9d\xcb\x93\x3b\x07\xbe\x46\xc4\xbc\xc7\x97\x79\x16\x98\xfa\x87\x2c\x7f\xcc\xd2\x7b\xbb\x70\x0d\x25\xc4\x82\xbc\x52\xe8\x11\x86\x17\x91\xad\xc2\x66\x35\x38\x8a\xcc\xb7\x15\x9d\xe6\x47\x38\x60\x14\x3e\x47\xbf\x78\xaf\xca\xfb\x0d\x9c\x5f\x4b\x7b\x6f\xc0\xbf\x44\xd5\xeb\x26\x65\x9e\xe5\x79\x7d\x16\x3a\x9e\xde\xff\x97\x9e\xa8\xa1\xe5\x24\x80\xe9\x79\xab\xf4\x42\x5b\x8c\xf8\x46\x05\x01\x24\x4b\x88\xf9\x50\x2a\x8b\x66\x47\x76\x8f\x43\xc9\x0f\xfd\x39\x02\x3d\x9f\x0b\x1b\x84\x5e\xf9\x86\x89\xb6\xb2\x6f\x46\x11\xa2\x78\xf3\x5b\xc4\xbe\x44\xf0\xe3\x57\x7b\xe8\x53\xb4\x69\xc6\xd8\x0c\x5e\xa1\x99\x31\x37\x36\x77\x17\xce\x98\xb7\xd9\xf2\xf0\x7b\xb4\x3e\x7d\xe9\x8f\x08\xde\x46\x70\x4b\x3e\x45\xa5\x44\x64\xa8\xb0\xa1\x4c\xfc\x23\x62\xe4\xf7\x00\x05\x6b\x67\x65\x1a\x45\x9b\xcb\xd0\x98\xbe\xa6\xe9\xfd\x2c\x25\x62\xc7\x08\x9e\x5a\xda\xb1\xdf\x2d\x4a\x19\xb2\x9f\x0a\x54\xf8\x17\x29\xe5\xed\x90\x62\xa2\x33\xf3\x35\x31\xca\x29\xe6\x4e\xe4\xd0\xee\xe6\xb9\x96\xb1\xbe\x53\x92\x60\x5a\x8e\xc3\x4e\x9a\xcf\x4c\x40\xe0\x25\x98\xcf\x2c\xc1\x7c\x66\xca\xf4\x89\x06\xee\x25\x2e\x5f\xd0\x5e\xc2\x88\x60\x88\x68\x87\xf6\x49\x9a\x76\xbe\xd5\x05\xcd\x74\xab\x0b\x5d\xea\xa5\xef\xb8\xcd\x43\xdf\xea\x52\x48\x70\xd4\x7e\xaa\x55\x2b\xc4\x8a\x5e\xb9\x21\x2a\xb4\x1a\x6e\x39\xbd\x9b\x99\xab\x1a\x5b\x2f\xc2\xff\x66\x16\xf6\xd1\x2d\x13\x54\x98\xd0\x1e\x65\x48\xc0\x66\x6b\x37\x20\x48\x1e\xc7\x94\x42\x02\x1b\x98\x84\xab\x53\x4a\x8b\x10\xb6\xf1\x06\x14\xe0\x21\x7b\x02\x41\xc8\xc2\x04\xa2\x95\xc0\x1d\x3c\x99\x6b\x43\xc0\x9a\xcd\xad\x07\xe7\x7f\xc6\xb7\x7e\x74\xf1\xc0\x9e\xe1\x92\x78\x6d\x24\x6b\x49\xca\x98\xc4\x04\x61\x36\xd1\x74\x18\xb2\x55\x99\x32\x1f\x1f\xda\x6c\x95\xab\xf2\x5c\x72\xdd\x98\x44\xb1\x6e\x3c\xde\x98\xe6\x32\xdd\xeb\x8f\x42\xe2\x74\x5c\x23\x2f\xd7\x65\xd9\x1c\x8e\x23\xae\x6b\x39\x36\x79\x48\xba\x62\xf7\x37\x7b\x4f\x67\x39\x5d\x26\x0c\x43\xc6\xcd\x8a\xfc\x17\x69\xf8\x1b\xc3\x90\xc8\xd6\x41\xe7\x37\xf5\xdb\x41\xe7\xb7\xae\xd8\x35\xcf\x44\xb7\x39\xc5\x1f\x06\xb9\x68\xe1\x85\x7a\x71\x65\xd9\xe2\xc5\xad\x64\x01\x93\x10\x31\xb5\x9e\x2f\x82\xbf\x27\xda\x6c\x66\x41\xb3\xb2\x2b\x37\x58\x96\x6b\xc9\x2a\xb9\x96\x58\xb9\x66\x13\x7f\xa2\xeb\xaf\x2e\xdd\x12\x98\x11\x0e\x56\xfe\xd9\x3b\xd7\x61\x1c\xae\xbf\x61\x29\xb6\xfc\x64\xd5\x8c\x41\xc8\xc6\x21\xdc\x6c\x06\xff\x91\x83\x6f\x87\x4b\xb9\xb3\x53\x81\xbc\xbe\x8f\x44\xda\x47\x6b\xfb\x47\xae\x9c\x2d\x1a\xc5\x3f\x4e\x5c\x0a\x93\x90\x6d\x87\x70\x15\xfe\xe2\xad\x62\xd3\x90\x7d\x55\x30\x0a\x59\x9c\xc0\x2c\x64\x9f\xe1\x2e\x64\x27\xf0\x55\x2d\xf3\x79\xbe\x9c\x58\xaf\xaf\x75\xd5\xdb\x2b\x0a\xf2\x2b\x35\x06\x09\xe1\xa5\x8b\x04\x55\xd1\xb4\xdd\xee\xfe\xee\x81\x38\xf8\x8d\x88\x76\xf7\xf1\xc3\x8e\xb1\xd5\xd2\x6c\x09\x24\x39\xdc\x9d\xcf\xb7\x6e\x12\x22\x68\x9f\xb7\xbb\x1e\xa7\x2d\xb2\x6d\x7e\xb5\xb7\x13\x82\xc0\x45\x40\x4f\x60\x18\x55\xb5\x34\x5d\xa4\x6a\x4d\x52\xcf\x96\xb1\xdb\x3d\xe4\x7d\xa4\xc3\x53\x99\x56\x53\xba\xac\xe2\xf1\x21\x9f\xcf\x77\x1e\x33\xc6\x78\xb3\x99\x56\x9a\x41\xef\x1c\x3c\x7c\xb4\x27\xf6\xeb\xfe\xd6\x0a\xc6\xfd\xce\xe3\x87\x07\x39\x4c\x91\x73\xa3\x53\x82\x79\xf8\xf0\xe1\x81\x38\xa8\x3b\xd4\x2b\x68\xba\x9d\xdd\x83\x47\x39\xcc\xc1\x4a\x34\xdd\xdd\xce\xde\x41\x41\xcf\xc3\xd5\x88\xf6\x0f\x76\x4b\x44\x3f\x5a\x0d\xf4\x68\xb7\x7b\xf0\x28\x07\x7a\xbc\xb2\xba\x9d\xce\xe3\xc7\xfb\x3b\x39\x50\x91\xee\xa3\x82\x6a\x67\x77\xff\xd1\xc3\x12\x54\x77\x35\xae\x83\x9d\x83\xfd\xa2\x9b\xba\x3b\xab\x71\x3d\x7a\xb4\x6f\x3b\xb3\xa6\x42\x96\x05\x1e\x06\x14\xa3\xc0\xfb\xa6\x49\x62\x33\x26\x2e\x16\x30\x23\x37\x61\xe9\x4f\x10\x92\x01\x79\x93\xe5\x91\x1c\x26\x64\x8f\xc2\x38\x21\x4e\xdb\xa1\xa5\x97\x3b\xe5\x97\xf8\x9b\x52\xb8\xdd\x30\x55\x76\xca\x53\xe5\x3a\xfc\xf5\xcb\xe6\x32\x9d\x42\xa5\xb7\x0c\x63\x4a\x3f\x33\x67\x48\x07\xb4\xcb\x33\x5d\x6d\xab\x74\x2b\x86\x60\x78\x55\x16\x11\x8c\x53\x37\xbf\xed\x43\xa4\xf7\xcd\xcc\xc8\xad\x59\xaa\x85\x99\xe8\xda\x5e\x33\x73\x14\xb2\x49\x02\x27\x1b\x0c\x09\xf9\x1b\x31\x42\xbd\x85\x16\xc4\xe9\x8a\xb5\xab\x96\xec\xb3\xd2\xa5\xe5\x3f\x36\x37\xa7\x6f\xf3\x04\x99\x2e\x3c\x75\x96\xbb\xd5\x5b\xd5\xd7\x5e\xa9\xaf\xa1\x52\x8f\xc5\xc9\xb5\x85\x73\x0d\xc2\x30\xa4\xe6\x5d\xc7\x6e\x66\x66\xd0\x93\x70\x4d\xf6\x7c\x53\xee\x9b\x25\xa4\xce\x0c\x27\xe1\x5f\x95\xef\xda\xf2\x2d\x5b\x7e\x25\x4c\x3b\x85\x31\xfc\x72\xf1\x17\x6d\x2b\xbe\x07\x21\x19\x12\xdf\xa8\x83\x9d\xec\xff\xd4\x68\xa8\xf6\x28\xf6\x57\x45\xe1\x79\xb8\xc1\x84\x36\x4a\x72\x45\x3f\xfe\x16\xfe\xad\xeb\xe6\xf2\xdb\x0e\x4b\xb7\xb9\x61\x04\x95\x3d\x3c\x8e\xac\x14\x69\xbc\xb7\xa3\x7c\x6b\x5b\x36\x03\xeb\xa0\xdf\xc2\x3a\xa8\xa1\xe9\xfb\x8a\x39\xc3\x24\x31\xd4\x77\x21\xf0\xce\x60\xe0\x75\xc1\xf7\x3a\xa6\x11\x98\x8f\x61\x51\x51\x68\x26\x9a\x20\x66\xb3\xc4\x9f\x51\x4c\x0a\x63\x56\xb0\x05\x85\xa7\xab\x10\xcf\xc8\x77\xd4\xae\x97\x71\xbc\x11\x70\x95\x00\x2a\x3e\x16\x09\x37\x48\x3e\x2f\x1b\xc1\x76\x11\xc2\xa4\x38\x65\x24\xc6\x56\x2d\x12\x67\xeb\xd4\x56\xf5\x62\x61\x51\xa1\xc9\x7a\xb9\xce\x04\xc8\xa5\x44\xbb\x5b\xbf\xf2\x0c\x84\xbd\xbd\xe8\x4d\xb8\xfe\xf6\x1d\xcc\x66\x99\xb8\xdb\xf3\xb9\x31\x1a\xf2\x37\xc2\xbc\x11\x2e\x4f\xb3\x60\xa6\x09\x43\x6d\xba\xd0\x72\xfa\xc8\x02\x59\x7a\x55\x8f\xc0\x64\xa1\x62\x29\xcb\xa4\x40\x15\x3a\xcf\x32\x99\xa5\xf1\xe4\xee\x00\x78\x29\xbf\xa4\xc1\x16\x40\x92\xa6\xb7\x8c\x98\xb1\x55\x42\x96\x60\x1e\xd2\x04\xef\x78\x4d\x5c\xd1\xab\x53\x59\x23\x29\x82\x30\x4f\xa3\x89\xd4\x71\x9a\x11\x18\xd4\xc8\x32\xdf\xb3\x04\xa1\x29\x85\x79\x0b\x72\xa2\x0c\x3e\x8e\x44\x51\x78\x17\xb2\xef\xf0\x21\x5c\x7d\xc5\x4e\xfd\x76\xda\xb4\x12\x03\x70\x13\xc1\x4d\x44\xf3\xcb\x3f\x79\x2e\x8a\x35\x26\xe7\xd4\x98\x9c\x53\xbb\xa2\x97\xe7\xe1\x7a\x67\x9a\x92\xd0\xfa\x94\xba\x21\x6f\xc2\xd4\xb1\x74\x47\x3e\xd8\x11\x08\x28\x44\xf5\xa8\x37\xac\x3b\x4d\x7a\x6a\xbe\xd6\x16\xb7\x12\x9a\xa0\x40\x14\x51\xd4\xde\x5e\xad\x6a\x9f\x66\x39\x98\xbd\x2b\x08\x87\x20\x3b\xf1\x5b\xdc\x3e\x5a\x4d\x6d\x9a\x65\x17\x35\x0d\xd4\x2e\x5e\x50\x74\x16\xae\x71\x1f\xed\xa4\xde\xa9\x93\xd5\x76\xd5\x50\xc0\x28\x81\xb3\xd0\xde\xc3\xf2\x7a\x0d\x96\xc7\x10\x20\x92\x8f\xeb\x6a\xd9\x87\x11\x02\x7c\x55\xab\xaa\xf9\x88\xe2\xfa\x75\x48\x8e\x34\xb5\xe7\x7c\xaf\x8d\xd6\x8c\x52\xf3\x38\x34\xb6\xfd\xfe\x02\xbe\x56\xfa\xa7\xe2\x5f\x68\x2c\x4d\x7a\xc9\x66\xc4\x8f\xd0\xbb\x58\x4b\x7e\x1c\x0b\x22\xd2\x6c\x1a\x90\x42\xd9\xea\x35\xbc\x0e\x89\xc0\x8d\x39\x59\x8a\xc7\x47\x49\xf1\xd5\xe6\x89\x46\xf1\x80\xd9\x82\xe0\x38\x34\xbd\xfa\x7d\x83\xd3\xc3\xfa\xf2\xee\xc8\xd7\x30\x73\xe8\x1d\x87\x78\xa5\x54\x7a\xe5\xf2\xcf\x90\xe5\x9e\xac\x24\x76\xe0\x95\xb2\x9e\x2d\x21\x07\xf1\x91\x76\xe0\xb3\xfd\x99\x4c\x8d\x74\x1a\x94\xde\xc4\x9a\x2b\x5d\x06\x19\x86\x72\x24\xd4\x54\x85\x52\xa3\xd7\x0b\x5f\x66\x89\x8f\x63\xf4\x9b\xbd\xc8\xfc\x66\x5c\xca\x48\xa3\xe7\x37\x76\xe0\x04\xfd\x69\xb7\xe4\x3b\x38\x23\x21\x85\xe2\x3a\x52\x5f\x8e\xdf\x39\xf0\x55\xe1\x97\x23\x6d\x0b\x61\x32\x86\x1c\x3e\x16\xe4\x59\x9e\x34\x91\x52\x78\x96\x36\x04\x73\xb7\xd8\xea\x7e\x86\xb4\x4a\x85\x03\x2f\xa2\x35\xb8\x5e\xe3\x6d\x47\xf0\x72\xe5\xca\xc8\x24\xa9\xca\x7e\xed\xd9\x8b\x75\x8d\xed\x63\x7a\xf1\xc5\x06\xa3\xec\x52\xc0\xcb\x10\xd3\x9e\x58\xbb\xec\xf3\xfa\xdb\x20\x8b\x84\xe1\xc4\xda\xd2\x14\xde\xaf\x74\x1e\x08\x19\x44\x03\xf1\xe5\xf8\xf5\xd3\x68\x32\x8d\xa4\xc0\x5c\xfc\x0b\xf8\x62\x50\x5f\x52\x78\xb2\x61\x7d\xc7\x0d\x8c\x8f\xf6\xe0\x3f\xba\x09\x7f\x84\x69\xf8\x2d\xfb\x0f\x07\x76\x30\x23\xe3\xd6\x7f\x38\xb0\x8b\x4f\xcc\x81\x8e\x7d\xc5\x1c\x3c\xf6\x04\x9f\x42\xf6\x09\xde\x86\x2b\x59\xae\xec\x93\x4a\x98\x26\x8a\x92\xec\x96\xb3\x6d\x7a\xcf\xcb\xb7\x9c\xa1\x7e\x2a\xe7\x73\x0e\x89\x59\x78\xed\x0a\x92\xb8\x1c\x02\x14\xfc\x46\xd8\xa3\x6d\x17\x14\x73\x06\xcd\x4d\x2c\x12\x18\x21\x8a\xd3\xc7\xfc\x52\x2c\x70\x53\x17\x94\xd5\x4b\x7f\x0f\xab\x77\x3c\xe9\x4d\x2e\xa8\x5b\xf2\x36\xb4\x97\x93\xe8\xd4\x80\xfd\x23\x5c\xef\x06\xfc\xdd\x48\xc1\x95\x22\x6a\x12\xc2\xb7\x04\x6c\xf8\x00\xba\xef\x86\xe8\x0d\xec\x2e\x40\x0d\xd9\x9a\xeb\xf4\x97\x15\x04\xf4\xe3\xe9\xd4\x21\xc6\x69\x71\xa7\x81\x5a\x75\xd3\x87\xa0\xd4\xc3\x4f\x3b\x99\x47\x31\xf3\xec\x75\x6b\x37\x15\x48\xd7\x6f\x75\x51\xa3\x73\xfd\x97\xad\x6e\x76\x65\x81\x57\x2d\x25\x5d\x7e\xd2\xaa\x17\x55\x59\xb1\xe2\xc2\x10\x0a\x1a\x5b\xf7\x70\x01\x62\xb8\x5e\x39\xcc\xd7\x45\x55\xb9\x7a\x2f\xf3\xb1\x04\xe8\x63\x19\xe0\xf6\x72\x7d\xf1\xc3\x34\x5e\xd9\xf2\x67\x0d\x10\xb1\xe2\xa6\xe0\xe2\x72\x3e\x5d\x2c\x73\x16\x3c\xa9\x68\x8c\x0b\x0a\xc9\x70\xcd\xb0\x6e\xcd\x88\x18\xa2\x7a\xe7\x6e\x2f\x28\xf0\xe1\xfa\xe1\x4f\x86\x99\x77\x25\x18\xb2\x64\xcd\x9e\x4f\x75\x1e\x44\x25\xdf\x6c\xea\x99\x8d\x4a\x9e\xd9\xcc\x0d\x6b\xfa\x9b\x57\x5c\xb0\x8b\x5e\xc0\x08\x67\x24\xf5\xc2\x46\x7f\xe5\x85\x8d\xca\x5e\x58\xa3\xf7\x58\x0f\x7a\x34\x64\xcb\xd6\xc9\x93\x90\x02\x51\x11\xbb\xe7\xdf\x3c\x3d\x84\xe0\xb9\x47\x64\xc4\xee\x83\xe7\xde\x75\x02\xc1\x57\xdc\x7f\xfd\xe4\x5d\x27\x0b\xea\x06\xcf\xcd\x0b\x19\xb9\xc1\x57\xf3\x4e\x46\xae\xff\x69\x01\x6b\x38\x57\x99\xaf\x05\xf7\x62\x6b\x55\xd9\x0f\x5d\xbf\x4d\x28\x72\xf9\x37\x9a\xb9\xdd\x32\x56\xf6\x49\x30\x34\x9f\x82\xe7\x60\xf9\x36\x65\xda\x6e\x9a\x5a\x7a\x80\x6e\x77\xaf\x04\xa6\x0a\xf7\xf1\xff\xcb\xdd\x9b\x68\xb7\x8d\x63\x0d\x83\xaf\xa2\xf0\xd3\xa4\x81\xf2\x95\x22\xd9\x4e\x52\x61\x8a\xbf\x8e\xb3\x3a\x8e\xb3\x78\x89\xe3\xb8\x3a\x9f\x0f\x48\x82\x36\x6d\x8a\x54\x40\x50\xb2\x9c\xe8\x5d\xe6\x59\xe6\xc9\xe6\xe0\x02\x5c\x44\x91\xb2\xab\xba\xbf\x9e\xef\x4c\x9f\xae\x98\x22\x16\x62\xb9\xb8\x1b\xee\xb2\xb1\x5c\x0b\xd4\xc8\x8c\x1e\x57\xd6\x4e\xd5\x8c\xb0\x00\x04\x76\x71\xb2\x72\xb6\xcc\xd0\x8a\x13\xa2\xf3\x1a\xa2\x50\xd7\x1a\x13\xa5\x82\xdd\xb4\x1c\x86\x6a\xbe\x1d\x0c\xf9\xbf\xd0\x19\x17\x80\x7c\xf3\x9c\x7f\x58\xff\xd0\x22\x1f\x9a\xe5\x4d\x38\x19\x52\x98\x27\x64\x48\x29\x64\xaa\xfb\x4a\x66\x8b\x41\x9e\xf4\xe2\x9b\xa7\x05\xbc\x6f\x21\x7c\xf3\xe0\x63\x66\xc8\x5e\xd0\x0a\xad\x62\x41\xc1\x0d\xd6\x2a\x0b\x83\x02\x9c\xd3\x60\xad\x8c\xd1\x99\x11\x57\x2d\xd5\x38\xd3\x12\xad\x1b\x60\x2a\x41\x7c\x37\x23\xdd\x46\xf9\xf6\x75\x46\x90\x48\x22\x27\x8b\x86\x86\xb4\xb5\xee\x71\x46\xde\x49\x92\xe9\x24\x7b\xdf\x75\xc2\xb9\x28\x58\xc7\xd6\xe4\x23\xb9\xeb\xdb\x5c\xf5\x39\x23\x51\x88\x23\x8d\x42\x8c\xf0\x1e\x21\x8e\xa5\x77\x8f\x08\x5b\x87\x98\x7b\xe4\x3b\x0e\xca\x6f\x5b\x27\xc5\xc4\xdd\x63\x6e\xcf\xef\x5e\xcf\xfb\xce\xcc\xac\x2a\xc4\x68\x5b\xab\xff\x2c\x28\x4c\x97\x46\xb8\xaa\x69\xcf\xbb\xff\xd2\x78\x49\xcb\xea\x32\x07\x92\xbc\x43\xf2\x67\xfc\x5d\xb1\x68\x69\x50\xcc\xb8\x2e\x74\x2c\x57\xf4\xab\x15\x57\x4c\x0c\xa3\x50\x4f\x56\xea\x3f\x59\xf9\xab\xec\x63\x4e\xa2\x20\xef\x81\x52\xad\x2c\x07\xde\xbe\x61\xa7\x0b\x10\x66\x93\xba\x81\x73\x2b\x9a\xd2\xb7\x74\x4c\xaa\x22\xeb\x9f\x71\xf1\x24\x4c\x72\x18\xb8\x15\x4e\x8e\x1e\x99\x34\xaa\x14\x22\x15\x56\x4c\xec\xbd\x8c\xe4\x8f\xd6\xc2\x02\xef\xad\x9d\x04\xe0\x7d\xb3\x2d\xb0\xc0\xdb\xb4\xbb\x81\x42\x8d\xd6\x4f\x0b\xbc\xa7\xf6\x40\x21\xcd\x84\xaa\x4a\x32\xe9\x7b\x6f\x55\xbd\xbd\x8c\xa8\xe7\x6f\x54\xd5\x56\x4f\x9b\xaa\x81\x7e\xeb\x7e\xa6\xaa\xd9\x7d\xc2\xab\xaf\x66\x42\xae\x2d\xed\xe6\x62\x81\x1f\x7a\x8a\x40\xef\x06\x90\x16\x9f\xd0\x4b\x8c\x9f\x9e\x92\x69\x5e\xa2\x06\xaa\x5f\xea\xb1\xa6\xc5\x40\x75\x37\x54\x6b\x8e\x28\x8c\x15\x19\x39\x4f\xe0\x65\x48\x6e\x05\x85\xdd\x8c\xc2\x65\xf0\x77\x92\x73\x2a\x4e\x75\x64\x40\x58\x50\xcc\x55\x6e\x12\x74\x4e\x82\x75\x8c\x71\x8c\xe1\x2e\x29\x5c\x04\xe6\xb6\x76\x16\x38\x51\x0c\xf3\xa0\x5d\x79\xba\x5d\x55\x9e\xde\x04\xcd\x42\xa1\x89\x4b\x03\xd7\xc1\xfa\x74\xd5\x3b\x81\xb1\xb8\x39\x0a\x8c\xfd\xcc\x71\xd0\x9a\x07\xfb\x75\x53\x51\xc7\x5c\x20\x2d\xe0\x6c\xed\x4c\xc7\x5a\x8f\x84\x91\x8a\x0b\x39\xe0\x6a\x1d\xbf\x91\x4b\xe4\x4c\x49\xe4\xac\xcf\x0a\x1e\xac\xa7\x3e\xe9\xf5\xbb\x0f\x1f\xea\x07\x66\x98\x32\xfd\xcb\x57\x5c\x79\x18\x10\xd5\xd4\x43\xfd\x4e\x6e\xc0\x68\x46\x73\xab\x28\xd7\xa2\xe9\x87\x58\x54\x65\x7d\xb9\xa4\xd4\xa9\x26\x7f\xe9\x73\xd0\xb7\xd9\x2f\x97\x57\xa4\x25\xf3\x4a\xa1\x3d\x49\x4a\xdf\x63\xed\x7e\x89\x06\xff\x1e\xde\xfc\xf8\x46\x21\xe4\x61\x46\x13\x33\xfe\xac\xa6\x0a\xd2\xeb\xf3\x32\x20\x99\x62\x84\x9e\xaf\xae\x90\xe6\xcd\x30\x97\x4e\x51\x9a\x2c\x8d\x20\x76\x92\xaa\x2e\x6b\x2f\x84\xa4\xcf\x8a\x3c\x33\x2f\x03\x92\xf4\x7d\xbc\xf4\x6a\xff\xee\x02\xce\x83\xa6\x3c\xc8\x75\xae\xd8\xcc\xb7\x7a\xf3\x88\x46\x97\xc0\x90\x43\xf6\x90\x43\x0e\x03\x72\x4c\x14\x45\xfb\x63\x50\xdb\x72\xfd\xb0\xbc\x00\x1a\x3c\x66\xe4\x3c\xc0\x4c\x66\x6a\x11\xf4\x94\x59\xdf\xaf\x4e\xf8\xd7\xaf\x24\x5f\x8e\x50\x2d\x87\x28\x97\x23\x5c\x19\x60\xb0\x9c\x96\x67\x2f\x84\xb0\xcf\x20\xec\xbb\x10\xf6\xbd\xfc\x63\xa1\x5a\x96\x80\x2e\xd6\x8f\xa6\x34\x72\xdd\x53\xef\x5c\x72\x15\xc0\x32\x58\xa3\xad\x59\xf3\xf2\xa9\xd1\xfd\x8d\xe5\xbb\xc0\xe5\x53\x02\x7d\x43\xb6\xe6\xbb\x60\x32\x46\x75\x8d\xbf\x58\x10\x2f\x27\xe3\xf9\x38\x46\xd3\xc4\xc6\xd5\x90\x45\xf2\x1e\xa6\x60\xc0\xab\xa6\xeb\xde\x0b\x8b\xb9\x99\x75\xd0\x53\xdc\x0f\x1a\x35\xce\xe7\x9a\x37\x7b\x5e\x99\x2e\x46\x28\xa0\x85\x7e\x7d\x59\xdb\x56\xcf\xc1\xb4\xa0\xf0\x31\x68\x54\x66\x08\x62\x04\x1e\x49\x6b\xd1\x26\xf7\xf5\x5b\x5b\x27\x23\x2c\xd5\x1b\xbb\xad\xb8\xd1\xb5\x31\x18\xab\x65\x90\xe4\x69\xe0\x30\x09\xef\xee\x60\x26\x4f\x03\xf2\xd3\x63\x4a\xec\x11\x36\x61\x4e\x06\xbb\x01\xa9\xab\xcd\x66\x01\xa0\x53\x49\xc9\xad\x9b\xad\x19\xcd\x4c\xb6\xb4\xb1\x2c\x14\x62\x8a\x2f\xf7\x6e\x6d\x01\xde\x07\x3b\x06\xef\xb1\xbd\x23\xc1\x67\xb6\x04\xdf\xb7\x1f\x0c\x17\x46\x41\xbd\xa0\xf0\xa9\x15\xf1\x4e\xc9\xbb\x00\xac\xb7\xaf\x8f\x2d\x45\x8e\xe0\x22\xd0\x7c\xf1\xa1\x21\x7b\xb3\x80\xa0\xfa\xcc\xe2\x42\x24\xc2\x82\x1d\x45\x13\x15\x11\x3c\x09\xd6\xdc\x7e\x11\x61\x4c\x26\x6f\x03\xe7\x2c\x86\x57\xc1\x5a\x5b\xec\xdb\x00\x66\xe4\xc4\xfc\x73\xc5\x21\xa6\x30\x46\x46\x64\x9f\xaf\x14\xcc\x64\x91\x98\xf9\xed\x1a\x79\xf5\x55\x80\xfc\xee\x07\x01\x02\x76\x70\x28\xa4\x89\x2e\x99\x95\xf5\x32\xbd\xb2\x71\xd6\xe8\xcd\x5c\xdc\xf1\x14\xae\xcb\xc7\xe1\x98\x27\x99\xec\xf0\x1b\x8f\x73\x9f\xfb\xf5\x10\x01\x1f\xb9\x9c\x25\xe2\xba\xa3\x17\xed\x79\xc5\x33\xab\x26\x2d\x4d\x02\x38\xc3\x2b\x98\xa3\xbe\x77\x49\x37\xac\x8e\xb5\xa1\x7f\xec\xc3\x61\x40\x84\x02\x83\xda\x85\xb7\xf5\x25\xe6\xb9\x85\x8b\xe0\xe9\x24\x89\x53\xde\x09\x44\x32\xee\xb0\x49\x88\xb7\x28\x7d\x56\x77\xa8\xfe\xc0\xa2\x20\x11\x63\xee\x77\x32\x11\x99\x3a\xe8\xd7\xa5\x49\xec\x9b\xe6\x83\x58\x06\x60\x89\x4b\xed\xa2\xce\xde\x96\x5a\x1b\x87\x99\x76\x41\xc8\xe7\xf2\x56\x01\xca\x27\xc5\xfd\x9e\x24\xe4\x55\xa8\xb7\xe8\xe0\xfe\x3d\xaf\xef\xf0\xd6\x74\xf8\xc1\x80\x65\xc3\x66\xe6\xf5\xe3\x0d\xeb\xd1\x8a\xf6\x55\x9b\xd6\x92\x75\x8c\x0e\xa5\xf0\x65\x8d\xd4\xb8\xab\xef\x15\xf1\x70\xbc\xf8\x5b\x0c\xe0\x9c\x7c\x0c\x74\x76\x76\x9c\xc2\x41\x48\x12\x8c\x8f\x63\x84\xe1\x80\x68\x01\x80\xc2\xb5\xa4\xb4\x9a\x0a\x95\xc2\x8f\xd5\x81\x55\xaf\xbf\x45\x71\xfd\xfd\x60\x58\x5a\x78\xa1\xe6\x5d\xf3\x51\x79\xbe\x47\x73\xa5\x8d\xea\xcf\xcf\x41\x7b\x42\xf8\x1f\x41\xb3\x29\x1f\x0a\xcd\x7a\x48\xef\x03\x67\x1e\xc3\xd7\xc0\xf9\x10\x13\x6b\xc2\x45\x1a\xa6\xf2\xad\x82\x8d\xd7\x37\x13\x16\xfb\x3b\x51\x64\xc1\xfb\x80\xc2\xb7\x35\xa7\x74\xbf\x10\xc3\x63\xb7\xad\xd6\x3e\x11\xf0\xd3\x9b\xda\x35\x26\xaa\x16\x3b\xe6\x90\xfc\xa9\x01\x09\x6d\x4f\xbf\xaf\xc4\xeb\xce\x13\x41\x8e\x39\x30\x8e\x19\x35\x67\xe4\xa5\x04\x25\xc6\xc4\x94\xe2\x51\x60\x5a\x7d\x29\xdc\x3b\xb4\xd4\x71\x7e\xd9\x29\xd7\x8f\xd9\xbd\xb6\x8b\xd8\xfe\xc2\x85\x71\x00\x71\x7f\xd7\xe8\x48\xf9\x6a\xd3\x62\xdb\x6e\x91\x90\xb3\x4b\xa4\xe4\x47\x48\xc9\x8f\x91\x92\x1f\x42\xe2\x88\xfe\x2e\x84\xaa\x58\xe7\x62\xb9\x57\x36\xc8\xf5\x99\x20\x45\xff\xcb\x9d\xb9\x20\xb3\xb5\xb9\x20\xd9\xfa\x5c\x90\x5e\x5e\x6c\xf2\x59\xc2\x3c\x23\x49\x43\x76\x48\xb9\x94\x1d\x32\xc4\x1f\x5e\x96\xca\x64\x8c\x60\x85\x41\x2c\xf8\xe8\x5a\x12\x9d\x01\x18\x73\x1d\x7c\xaf\x25\x90\xe4\x74\xb4\x4b\x62\x58\x4a\x22\xc9\xa9\xb6\x70\xcf\x5c\x25\xbe\x6c\x2f\x80\xb9\xce\xa1\x20\x56\x90\x78\x59\x6a\x51\xf0\x56\xf7\xa2\xfd\x72\x7f\x8f\xe8\xbd\xbd\xb2\xe3\x3e\x1b\x59\x96\x2d\xfa\xee\x15\xe0\x56\x7f\x0e\x0c\xc3\x2e\xfa\xee\x35\x1d\xa9\x7f\xed\x5d\x85\xda\xaf\xf3\x90\x37\x0b\xaa\xd6\x03\x89\x53\x57\x92\xcc\xa5\xc0\xdc\x66\x87\xd6\x52\xc9\x50\x1a\x11\x34\x8e\xe0\x93\x5a\xb7\xca\x20\x2e\x03\x98\x87\x44\xd1\x48\x35\x88\xbf\xfe\xc1\xad\xc6\x89\xaa\x7e\x86\xb0\x9b\xd4\x6d\xba\x4c\x25\xb6\xbf\x5c\xa9\x26\x9b\xef\x11\x61\x4a\x50\x2d\xeb\x1a\xe7\x8b\xd0\x6d\x64\xd2\x74\x8f\xcc\xc6\x9c\x8c\xde\x94\xf6\xdd\xd1\x05\x11\x50\x3f\xe0\xd4\x5c\x18\x99\x24\x83\x16\xe6\x6b\x51\xc0\x61\xd1\xd2\xe2\xe1\x9c\x48\xf8\x98\x68\xb5\xcf\x69\x02\xb2\xef\xed\xc2\x8c\x70\x57\xbb\x7e\x15\x0b\x93\x98\x85\x41\xd0\xeb\xb9\xf3\x1e\xba\x9a\x1b\xd3\x93\x05\x85\xc0\x5d\x87\x7d\xe3\x3f\x9c\x41\xc9\x9b\x2e\xa3\xe3\x8e\x50\x88\xa8\x37\xd4\x5e\xcf\x6a\xfa\xae\xbb\xde\x94\xa9\xda\x9b\xac\xf7\x26\xcd\x5d\xba\xe8\xb3\x6a\xbf\x18\x7c\x34\x51\xac\xa6\xc4\x25\x4e\x5b\x11\xd3\x3b\x49\xe6\xc4\xc5\xf9\xc3\xa9\x56\x36\xba\xcd\xd7\xfa\x83\x3f\x44\x6e\x78\x78\x8e\x37\x49\x8d\xbe\x90\x6a\x7c\xbc\xef\x56\x47\x58\xbc\xea\xbb\x05\xa2\xe6\x15\x09\xdb\x78\x05\xe6\x56\x84\xaa\x28\x67\xae\xf2\x2a\x06\xc8\xf4\x65\x1a\x2f\x41\xff\x90\xfc\x99\xf5\xf1\xde\xac\xcf\xbe\x17\x00\x8b\x91\x60\xdc\xfc\x8b\xb9\x45\x86\x0b\x9e\xc3\x96\x9a\xb2\xbe\xbe\x3f\xf3\x74\xf3\x45\xdd\x61\xb2\xda\xcf\xc3\x87\xc5\x63\xde\x69\x82\x9d\x86\x4e\x62\x92\xb7\xba\x28\x8c\xeb\xcf\x30\x60\xd5\x8f\xe1\x66\x24\x68\x4c\x9d\x48\x14\x14\xf1\x21\xcb\x1f\x3c\x18\xf2\xad\x3f\xe2\xd1\x8c\xa4\x2e\x88\xde\x36\x30\x25\x79\x44\x2e\xc4\x1b\x43\xf3\x1b\xf3\xef\xe7\x4b\x95\x8b\x52\x85\x0b\xe5\x21\xf9\x93\x9b\x59\x14\x4a\x40\x0a\xbe\xdb\xce\xbd\x44\xae\xb6\xc9\x40\x45\x69\xd3\x96\x17\x46\x1a\xab\x34\x53\x27\x4f\x96\x7d\x57\xdb\x59\xb9\xc0\x37\x14\x6f\x1d\xb8\xc0\x7b\x08\x83\xfa\x94\x74\x5b\x3f\xaf\x33\xd6\xc4\x68\x69\xa4\x6a\x8e\x5d\xe7\x3d\x5c\xb6\x93\x40\x23\xca\xe6\x23\xf9\x2a\x74\x26\xe7\xc6\xb8\x08\xa6\xd2\x83\x0b\xa2\x53\x99\x3f\x7c\x78\x41\xb8\xe1\x52\x50\xb7\xb6\x66\x51\xf6\x24\xe0\xad\xb1\x59\x97\x0b\xb7\x49\xe4\xd6\x4c\x0f\x2d\x14\x8f\x7a\x90\x63\xf4\x89\xe3\xda\x35\xaa\xeb\x92\x53\x94\x57\x26\x2e\xcc\xc8\x47\x09\x43\x90\x14\xde\x9a\x7c\xdd\x99\x83\x96\xe6\x20\x1c\x9d\x68\x2e\x03\x49\x1f\x6d\xfe\x1a\x50\x3c\xbe\x33\x72\x98\xc0\x8c\x4c\x5d\x10\x5a\xc9\xdb\xdc\x5f\x86\xfd\x69\xcd\x7d\xec\x7c\x15\xea\xeb\x99\x13\x3f\xca\x14\xcd\x79\x24\xc1\xa4\x12\xca\x33\x49\x5f\xba\x84\x1b\xbe\x92\x4b\x88\x39\xe9\x3f\xd6\xaa\x64\xc0\xdc\x86\x37\x12\x39\xd9\xd2\xcc\x62\x34\x7c\xb4\xf5\x1b\xc9\x36\xe4\x06\x89\x7b\x82\x3e\x8a\xa9\x3d\x58\x50\x98\xad\x43\x56\x39\x72\xc8\x85\xf5\x07\xbc\xcf\xfa\xee\xaf\x5f\x75\x84\x90\x1f\x63\x06\xcb\xf7\xdc\x68\x7b\xa4\x9e\x73\xaf\x8d\x4c\x71\xaa\xb1\xe3\x81\x70\x38\x48\x67\x97\x48\x85\xf5\x99\xa2\xf1\x3c\x4a\xb9\xc6\x4a\x5f\x51\xb2\x2c\x3a\x37\x37\xa4\x20\x15\x4f\xbb\xa0\x30\x77\x9b\xf4\x8f\x27\x24\xa6\xfd\xab\x24\x8c\x91\x3c\xc0\x4d\x1b\x4c\x58\xb9\x72\x5c\xfd\x15\x8a\xbc\xeb\xdd\x1f\xc5\xf6\xdc\x25\x73\x32\x73\xf5\x2e\xe8\xbd\x35\x18\xf4\xba\x05\x83\x2e\x77\x46\x0b\x4d\x76\x03\x4c\xe5\xd3\xd9\xe8\x6f\x3e\xfe\x6d\xcc\xc9\x8c\xdc\x18\x1a\xf5\x1b\x19\xf6\x50\x13\xb1\x73\xcf\x31\x0f\xf2\x21\x0f\xed\x39\xb9\xd6\x98\x7e\x46\x2e\xdc\xc2\xdb\xf9\xc8\x75\x5e\xc1\xb1\xdb\x78\xc5\x94\x47\x1c\x2b\xf8\x9e\xa7\x65\xa8\x30\x5e\xa5\xa4\xbc\x42\x49\x35\xc1\xbe\xb4\xa5\x62\x01\xee\x4b\x55\x6b\xd1\x44\xe6\x24\xd4\x43\xdd\x27\x1c\x7e\xb2\x73\xd5\x99\x5a\x7e\xde\x67\xe7\xe0\x4d\xed\x5d\xc2\xfb\x1e\xc6\x6d\x41\x13\x32\x25\x24\xb9\x91\x7d\xba\x58\xe6\x93\xb0\xec\xf9\xba\x2e\xb3\xa2\xc7\x9c\x55\xca\xa8\x9a\xcc\xb4\xd6\x5f\x25\x69\x1d\x36\x77\xc7\x7a\x7a\x25\x0f\xb4\x5d\xab\xc1\xb6\x54\x0d\xed\xb7\x5b\xad\xf7\xb8\xde\xd3\xeb\x7a\x4f\x5b\xf5\x9e\xf6\xeb\x35\x0a\x23\x75\xe6\xe4\x93\x51\x53\x65\x98\x45\x74\x9f\x30\xf8\xe9\x46\xb6\x87\x01\x46\xce\xe9\xe8\xd4\x9e\x91\x2e\xc7\xc8\x6d\xfa\x05\xeb\xbb\x91\x8d\x88\x7b\x38\xd0\x09\x89\x8e\x5c\xd8\x71\x75\x75\x28\xf1\x7c\xa3\x24\xf1\x19\xf5\x96\x6a\x85\x16\xe0\x66\x14\x52\xf5\x19\x6f\x4f\x5f\x4d\x55\x67\xbb\x12\x5b\x8e\x23\xc7\x97\x2b\xa0\x5e\xbb\xc6\x6e\xe2\xac\x0d\x90\xd1\x2f\x10\xbc\x2f\xfa\xd6\xe2\xca\x5d\xe7\xd0\xe6\xbd\xb4\x05\x78\xef\x55\xfd\xcf\xb6\x04\x6f\xcb\xe6\xaa\xd1\x4b\xd7\xf9\x22\xe0\xdc\x75\x1e\xf5\xff\xfb\x11\xec\xb9\xce\x0b\x41\x86\x8f\x06\x14\xf6\xef\x09\xef\x95\x18\x7b\x5b\x68\xe8\xc7\xfa\xdd\x11\xb7\xf5\xce\xbd\xb0\x11\xc1\x1e\x64\x20\x31\x14\x42\x75\x8b\xea\x00\xa3\x3d\xb5\x71\xdd\x13\x09\x6a\x6a\x16\x4a\xc4\xde\x17\xdb\xb2\x16\x90\xef\x06\xef\xbb\x2f\xd4\x3a\x16\xce\xdb\x88\x75\xcd\x01\x7a\x6d\x0e\x50\x2e\x25\x15\x07\xe8\xde\xa0\x55\x1e\x0b\xf6\x7c\x65\x7c\xd9\xdd\xc3\xcb\x81\xa5\x3d\x35\xb8\x9b\x2c\x14\x28\x65\x94\x9a\xb9\x50\xda\x08\xb9\xf9\x10\xd1\x3f\x7d\xcd\x31\x72\xf7\x56\x8f\x47\xd3\xf8\x8d\xd3\xbb\xe9\xae\x19\x27\xb9\xb7\x36\x22\xc5\xcc\x88\x0a\x19\x5d\x60\x30\xa6\x16\x48\x5d\x50\xf8\xb8\x5e\xa2\xcf\x53\x72\xe6\x96\x4e\xbb\x6e\x8b\xba\x37\x0f\xc1\xe4\x32\x14\xdc\xd9\x1e\x4a\xee\xac\x8b\xa2\xbb\xbb\x03\x81\xfa\xf5\x0e\x5c\x27\xdb\xb0\xfe\xeb\x51\xae\x5a\x4b\x1d\xee\x12\xb7\xc8\xb1\xb7\xaa\x76\xc4\xc9\x2b\x64\xfb\xce\xc8\x5b\xc5\x22\x0d\x70\xa3\x23\xbc\x35\xf2\x1b\x52\x77\x46\xb5\xf8\x50\xb1\x13\xa1\x95\x39\x22\x0f\x6f\xcf\x7e\x65\xf2\x8c\x62\x94\x47\x64\x48\x5a\x37\x3c\x5c\x80\x2b\xa9\x49\x47\x8a\x26\x9c\x6d\x79\x72\x4a\x4c\xfc\x2e\x81\x0b\xad\x62\xd5\xb0\x96\x69\x27\x65\x6b\x81\x8c\x9a\xab\xa0\xec\x45\x70\xc7\x47\xb1\xd4\x95\x70\x19\x90\x56\x44\xa5\x78\x0c\x44\x55\xc8\x26\x55\x9c\x97\xce\x89\x87\x74\x5b\xd4\x09\xcf\x39\x89\x12\x60\xab\xd1\x33\x43\x7c\xbb\x02\x29\x71\x46\x22\x35\x0b\x0c\x8b\x45\x9f\xaf\x6c\x8b\xaf\x46\xb0\x67\x47\xe0\x32\xdb\xef\xbb\xcb\x18\x42\x2d\xcc\xd4\x99\x91\xd8\x05\x09\x8c\x42\xd7\x99\x11\xa9\x9e\x93\x95\x9e\x96\xc3\x49\xc8\x3e\xbb\x1c\x05\x76\x88\x51\x25\xf0\x47\x98\xd8\x1e\xb0\xae\xdd\x55\x1f\x9a\x2a\xc8\x45\xda\x8c\x65\x33\xb2\x6f\x36\xf0\x1b\x07\x91\xa9\xd3\x71\x10\xa0\x6c\x48\xed\xb2\xec\x6b\x5e\xf6\xc6\x94\x41\x59\x96\x65\x58\xf6\x21\x20\xbc\x4a\xad\x2b\x87\x59\xe8\x23\x27\xd4\x91\x4b\xc9\x3e\x91\xf0\x13\x13\xd7\xa2\x71\x6e\x19\xf1\xec\xe9\xda\x16\x47\x0d\x2d\x7e\x5f\xdb\xe2\xb8\xa1\xc5\xb0\x7e\x3a\xdc\x93\xfa\xe9\xd8\xc6\xa5\x1f\x3b\x33\xe2\xa1\x1d\x14\x24\x6a\xf1\xc7\x78\x56\xc6\x7d\x17\x2e\x9d\x71\xdf\x83\x89\x53\xae\x80\xd4\x2b\x70\x49\x61\xec\xa4\x64\x46\x3e\xba\xd0\xed\xbb\xd7\xb8\x4e\x13\xc7\x1f\x55\x58\x21\x1c\xdf\x98\xc2\xe4\x3b\xa5\xf6\xa4\xbe\x91\xb8\x45\x27\xc8\x4c\x4f\x0a\xb4\x3d\x71\x6e\xc8\xb1\x0b\x2e\xda\x3b\x32\x05\x0a\x97\xce\xa4\x9a\x46\x5c\xcf\x83\xd9\x53\x67\x82\x33\x29\x07\xc6\xf3\x81\x15\xd8\x71\xea\xdc\x90\xfd\xb2\xb3\x50\x75\x36\x5d\xed\x6c\xc7\x9e\xd6\xba\xca\x6a\x5d\x3d\xab\x63\x99\x37\xf5\x75\x1c\x6a\x34\x73\x51\x55\xad\x96\x10\x8b\x46\x65\x17\x20\xfa\xec\x35\x1d\xcd\xc8\xb7\xe2\x87\x3d\x23\x5f\x8a\x1f\xe0\xfd\xd0\x38\xfb\x6b\x40\x1e\x0c\x2b\xd8\xf8\x12\x91\xd7\x85\xb3\xe5\x38\x0e\xb9\x70\xce\x49\xa0\x86\xa6\x08\xf0\xc3\x87\x17\x7d\x77\x84\x28\xea\xa3\x12\x5c\xbe\x0a\x72\x81\x04\x98\x52\x7b\x9c\xac\x0e\xe4\x42\x7d\xe3\xb2\x38\x14\x5f\x03\x72\xa9\xe6\x9d\x24\xc0\x32\xb8\xe2\xe4\xd2\x28\x76\x16\x14\x4e\x5d\x67\x1e\xc3\x3b\xb7\xaa\xc4\xc6\x78\x84\xaf\xd8\xfc\x53\xf0\x95\xf3\x6b\x0b\x4e\x5d\x0a\x9f\xda\x84\xd5\x18\x78\x7b\xa6\xe4\x3c\x38\xe1\xb2\x15\x4b\x1e\x9a\xb0\xd5\x96\x65\x60\x32\x21\xf3\x51\x51\x35\xef\xa9\x36\x59\xef\xc6\xe6\xc5\x3c\xf5\x0c\xa5\x9a\xe1\x1b\x4e\xb4\x6f\x01\x53\xe5\x94\xc2\x3b\x97\x14\xe6\x65\x87\x6b\x39\x2b\x93\xd8\xaa\xea\x52\x83\xc1\x35\x5c\x63\x04\xf2\x45\xac\x35\xf8\x4e\xb5\xd1\xff\x82\xc2\xad\xeb\xcc\xc8\x17\xad\xb8\x33\xba\xe7\x77\xaf\xac\xef\x14\x3d\x7b\x5e\xb9\xce\x75\x0c\x6f\x5b\xc9\xed\x7b\x49\xe2\x47\x28\x94\xbf\x71\xef\xef\xfa\x27\x36\xe2\xba\xb3\x89\xb6\x1d\xe0\x7d\xf7\x33\xba\xff\x97\x35\xb9\xf6\xb5\x02\xe1\x88\xdc\xab\xef\xa0\x75\x93\xab\xb4\xec\x8d\x46\x21\x33\xf2\xd6\x85\x18\x33\x96\x3f\xe1\xdb\x26\x54\xc8\x87\xf6\xbb\x03\x46\x66\xe4\xc0\x48\x61\x7d\xf6\x75\x41\xe1\x8b\xdb\x7e\x31\x32\x0b\x61\x73\x5b\x7f\xa3\x68\x06\x4f\x06\xb8\x7f\x2f\xd6\xb7\x1b\xf2\x2d\x3d\x2e\xbc\x37\x5a\x5f\xf7\xc9\xa0\xec\x5e\x55\xff\xdc\xaa\x0a\xaf\x8d\x7f\xf2\xff\x97\x4c\xf9\x14\xde\xbb\xed\xf7\xd8\x83\x3f\xe2\xd1\x9c\xbc\x77\x21\xfe\x3f\xff\x67\x08\xbb\x44\xa8\x6d\x18\x3e\x8c\x47\xbb\x44\x82\xa0\xb6\xa4\xb6\x12\x7f\xbe\xae\xd1\x31\xbd\xd7\x42\x28\xaa\xa5\xe1\xdb\x9a\x6f\xed\x92\x19\xf9\xea\x42\xdc\x1b\x73\x22\x29\x1c\xa1\xf6\x48\x83\x55\x9c\xb6\xf7\xff\x4d\xf5\x6f\x0d\x30\xd7\x86\xde\x44\x91\xde\xbd\xe7\x05\xec\x0e\xf9\x16\x36\x92\xe9\xfd\x20\xd7\xdd\x52\x10\x28\xee\xe9\xe2\xce\x53\x67\x46\x5e\x08\x18\x60\x9e\xa7\xd4\x91\x0c\x98\x7a\x75\x12\xc0\xa9\x0b\x59\x4a\xc1\x5b\x33\xb5\x73\x09\x44\x61\xd8\xd6\xeb\xb8\x49\x96\x5e\x12\x7d\x85\x2a\x16\x94\xc2\x9f\xdf\x73\xaf\x5f\xb5\x2b\x49\x7a\xcf\xd8\x29\x61\xda\xbe\x2b\xda\x3a\xe2\xf3\xa7\x23\x63\x1e\xa1\x8d\xa1\x21\x58\xed\x3b\xae\xdf\x6b\x17\x29\x4b\x74\x9a\x92\xaf\x68\x7e\x7a\x4e\x2c\x73\xe7\x92\x5a\x30\x23\x5e\x0a\xdf\x32\x20\xc2\x11\xb4\xef\x5e\xeb\x0b\xb0\xd2\xbf\x88\xa5\x44\x60\xc2\x4d\xf5\x3a\xf7\x4b\xc2\x97\xec\x54\xbf\xd4\xa9\x45\x30\x3a\xcf\xa9\xab\xde\x9f\x98\xf7\xc9\x78\xcc\x63\x99\xbf\x3d\x36\xf7\x7b\xbe\xa5\x73\x8b\xbf\x72\x75\xbe\xf1\x53\xbc\xac\xf2\x4d\x3a\x1f\xf4\x4f\x4d\xc1\x62\x93\x49\x14\xea\xf0\x54\x8f\xae\xd2\x04\x53\x45\xbe\xae\x69\x0c\xdf\x06\x64\x4e\xc2\x14\x57\xe4\x56\x6b\x75\xdd\xd6\xf5\x66\xc7\x8a\x93\x38\x06\x86\x9c\xd9\x09\x4c\x6d\x01\xa9\x1d\xf7\x53\x60\xa7\x36\xa6\xa7\x77\x7d\x1b\xf3\xba\xb8\x07\x36\x66\xad\xdf\x53\x92\xf0\x82\x42\xda\x0a\x1e\x41\x48\x10\x82\x37\x98\xf6\x8d\xa3\x10\xa5\x4e\xa3\xf0\x20\x45\x38\x26\x74\x01\x7e\x6a\xdc\x7d\x66\x16\x3c\x19\x6c\xff\xce\x1f\xe3\xa2\xf8\x16\x60\x38\x04\xfc\x71\x69\xc1\xd6\x13\xf3\x3c\xb6\x34\x66\x57\x5b\x62\xe1\x41\xf9\x4e\x61\xba\xfe\x70\x3d\x5d\xf1\x82\xc3\x97\x15\x87\xb6\x5f\xbf\x9e\x2e\xd4\xb0\x9f\xf6\xee\x63\xf7\xfa\x9f\xc8\x99\x67\x96\xaf\x9b\xb6\x50\x3f\xc6\x48\x4c\x47\x43\x7b\x50\x04\x1b\xbe\xcb\x3a\x77\x6b\x58\x1b\xe6\xe3\x67\x1b\xb2\x36\xd2\x67\x83\xfc\x55\x31\xd8\xe1\x66\xf1\xae\x18\xf0\xf0\xf1\x30\x7f\x57\xd0\x86\xe1\xef\xc5\xbb\x82\x3e\x6c\x0e\x37\xf3\x77\x05\x8d\xd8\xdc\xde\xca\xdf\x15\x74\x62\xf3\x69\xf1\xae\x12\x66\x61\xb0\xbd\x21\xeb\x2b\xb3\xb5\xb5\xbd\x81\x76\x12\xe3\xf4\x6e\x2e\xe5\xb2\xb5\x8e\xa7\x56\x6f\x63\x46\xba\x78\x56\xe8\x86\x62\x7d\x27\x69\x2b\x99\xad\x2f\xed\x56\x1d\x02\xf4\x6e\x6c\x3e\xb3\x37\x7f\xaf\xc3\x42\x9d\xe6\x6e\x0d\xea\x44\x77\x58\x0f\x8c\x31\xc8\x97\xb6\x1e\xe7\xa2\x1e\xd3\x62\x50\x8f\x5f\x31\x5c\x5d\xc4\x95\x15\x44\xfa\x7a\x91\xde\x79\x87\x30\x23\x13\xbd\x3a\x90\x39\x09\x33\x86\x98\xc3\xcd\x3f\x9c\xec\xd7\xaf\x63\xf4\x1b\x2b\x2f\x45\x7f\xb2\xaf\xb6\x04\x36\xb1\x05\xb8\x5b\x76\xbc\x30\x4c\x5c\xc8\x48\xb6\x31\xa4\x20\x1d\xd9\x43\x86\x75\x96\xb6\xdf\x46\xcd\xc8\xd8\x7c\x0f\xcf\xa7\x30\x57\x45\xf3\x54\xdb\x16\xb9\xac\x59\x0b\xc1\x26\x0b\x0a\x37\xa6\xd2\x3c\x6d\xa8\x44\x12\xdc\xed\x4d\xfa\x68\xeb\x97\x12\xf9\xae\x5b\xce\x14\x70\x47\x3c\x6f\x3b\xf3\xd2\x09\x90\x34\x7b\x8c\x48\xba\x31\x5c\xf1\x36\xb8\x4c\x41\x57\x20\xd2\xb9\x49\xd5\x43\xc8\xc8\xd6\x6f\xb2\xb7\x49\x1b\x42\x50\x17\xb5\xe7\xaa\x6a\x21\x35\x2e\x03\x06\xef\xcd\xc8\x34\x45\x0c\x5f\x83\x10\x53\x32\x2c\x4a\x9e\xd4\x4a\x36\x8b\x92\xa7\xb5\x92\xad\xa2\xe4\xf7\x5a\xc9\x76\x51\xf2\xac\x56\xf2\xb8\x28\x29\x01\xcb\x14\x3d\x51\x45\x35\x08\x43\xf2\xbd\xb3\x86\x7c\x1f\xa3\x71\xd6\x1f\x83\x51\x6c\x0f\xfe\x38\x46\xa6\x6d\x24\x90\x67\x3b\x5a\xd3\xaa\x7e\x66\xe7\x64\x47\x2d\x41\x09\xa6\x3a\xaa\xc7\x1a\xd6\xe5\x28\x05\xcc\x76\x69\x80\xec\xb3\x9b\x3f\x7d\x28\x99\xed\xd7\xe9\x3a\x37\x1f\x45\x86\x7e\x8b\x37\x9e\xf0\xed\xdf\x04\x86\x81\x92\x1b\x4a\xd4\x3b\x6b\xfd\xe8\x0d\x79\xad\x3e\xfa\xa5\xf8\xd4\x8f\xe2\x49\x14\x03\x79\x51\x7e\xfe\xaa\x0d\xdf\x23\x59\x35\xf4\x8a\xa4\x8a\xfb\x3b\xd6\xed\xd5\x92\x9c\xe9\xc7\x9e\xa4\x8f\x9e\xf0\x6d\x04\xf2\x97\x69\xeb\x75\x72\x8a\x14\x5a\x42\xa6\x78\x23\xd5\x32\x08\x09\x47\x4e\x43\x3d\xf4\xd4\xe4\x32\x8a\xd6\x0b\x57\x69\x61\xf4\x7b\x41\x32\x28\xaf\xf8\xc4\x73\x5e\x56\x96\x15\xbf\x50\x09\xa6\x15\xa7\x74\xc4\xd1\x9d\xe2\x7c\xcd\x9e\xce\xc9\xcb\x14\xaf\xc2\xae\x53\xb4\x0c\x3d\x4e\xb1\x98\xc2\x00\xad\xad\x9b\x5a\xd6\xb3\x42\x15\x87\x22\x27\x20\xdb\x76\xbd\x73\xd3\x2b\x94\x9b\x81\x3f\x71\x33\xcc\x93\x30\x55\x06\x85\x02\x6b\xeb\xaf\x77\x33\xa8\x34\xdf\xbc\x6f\xf3\xc1\x52\xb3\x61\xd9\xec\x3c\x85\xe1\x50\x87\x38\x58\x46\x1f\x58\xb4\x59\x29\x19\x2c\x95\x0c\x2a\x25\xb5\xee\x2a\x25\x5b\x4b\x25\x5b\x95\x92\xed\xa5\x92\xed\x4a\xc9\xe3\xa5\x92\xc7\x95\x92\x27\x4b\x25\x4f\x2a\x25\x4f\x97\x4a\x9e\x56\x4a\x7e\x5f\x2a\xf9\xbd\x52\xf2\x6c\xa9\xe4\x99\x2e\xa9\x07\xe1\xc7\x09\x19\x3f\xc8\x05\x85\xfd\x76\x78\x47\xa6\x3a\x62\x25\xbf\xf7\x93\x5d\xd9\x02\xd8\xb5\x9d\x97\x28\xbc\x7e\xa3\x09\x58\x0c\x4c\xa0\x82\xf7\x56\x3d\xee\x68\x3d\xcb\x47\x14\x92\x76\xd3\xb5\xd1\x1c\x8f\xed\x43\x34\x3f\x60\x27\xea\x21\xa6\x30\xb5\xe7\x64\x3f\x05\xf4\x06\x46\xeb\x3b\x92\xa6\xf0\x74\x93\x3f\x46\x08\xe7\x14\x52\x55\x11\x59\x7f\xcb\x82\x8c\x11\x8c\x23\x45\xa9\xe2\xbf\x0f\x39\xf9\x98\x2e\xb7\xa0\x8a\x1f\xdf\x91\x8a\x1b\xd7\xa5\xaa\x97\x3d\xfb\x01\xd2\xf3\xd3\x56\x0c\x84\x88\xa3\x17\x2b\xe4\xb9\xa0\xf0\x2e\xbd\xc3\xd5\xc7\x98\xa6\x56\xa2\xc7\x7c\x4a\xdb\x15\x30\xbe\x4e\x7c\x71\x82\x8e\x30\x4a\x96\x70\x50\x50\xf0\x1c\x94\x1f\x12\x67\x37\x23\x3e\x23\x59\x4a\x98\x36\x91\x28\x7e\x7b\xe5\x35\x80\x59\xb9\x2c\x5f\x39\x5e\xac\x9c\x89\xf7\x5a\x5f\xa6\x19\x39\x4d\xb5\x47\x46\x75\xad\x3c\xbd\x40\x7a\xb5\x8b\x35\x62\x95\x35\xba\x8e\x1d\xd6\x1a\x17\xb7\xba\x8f\x99\x1a\x09\x57\x5d\x4b\xd5\x25\x03\xf7\x5a\xc9\xa5\x07\x8a\xbb\x39\xb2\x3d\x70\x4f\x6d\x0c\xb7\x7c\xb6\x36\x1e\xee\x85\xcd\xc1\xbd\x54\x5d\x24\xaa\xf5\x99\x09\x09\x2a\x1c\x0c\x2d\x11\xa6\xaf\x7f\x64\x2c\xc2\xa8\x12\x41\x82\xf0\xf1\x60\x90\xc7\x7d\x4d\x0f\xf9\x05\xbf\xb1\x20\x30\xe1\x21\xa6\x2c\xca\x78\x19\xc5\xa2\x1a\xc9\xf5\x4c\xdf\xf9\x9e\x0a\xa7\x1a\x01\xf6\xae\xa0\xb7\x79\x52\xbc\xbf\x14\xf0\x36\xcf\xb0\xf7\xf7\xa3\xdd\xb6\x44\x9e\x3d\x34\x86\xde\x87\xa9\xd3\x1e\xdd\x03\xc3\x81\x9c\x9a\x70\x20\x4a\x66\xce\x57\xa3\x90\xaa\x8b\x17\xa5\xf8\x9d\xbf\xaa\x85\x0f\x59\x09\x16\x52\x4a\xff\x27\x09\xf9\x2c\x70\xa4\xd7\x65\x38\x0f\x38\x69\xa4\x61\x2d\xba\x05\x0b\xc4\xf7\x6a\xca\xcd\xfd\x04\x24\x94\x76\xf3\x87\xa9\xd6\xf8\xde\xa6\x0e\xe1\x89\x13\x84\xf5\x18\xd5\x31\xd9\x89\x09\x4f\xc8\x2b\x26\x79\x3f\x4e\x66\x44\xdf\xdf\x52\x78\x95\x56\x35\xe2\x26\xcc\xfb\x4b\x35\xdb\x44\x68\x8d\xf8\xdb\xf4\xae\xc8\x96\xb9\x8b\x90\x89\x98\x33\x32\xc1\x8b\x46\x26\xf8\xd2\xc8\x38\x71\x8d\x66\x92\x4c\x89\xf1\xb9\xe9\x33\xe0\x68\xe1\xc7\x30\xad\x0c\xfa\xba\x30\xe3\xf3\x92\x99\xbf\xdc\xfc\x95\xe6\xaf\x41\x1e\x2f\x84\x12\xef\x6f\xc8\x99\x3a\xbb\x96\x05\x0f\x86\x06\xd2\x95\xd8\xfe\x26\x75\xd4\x71\xb3\x2c\x75\xde\xd4\xbf\xa7\xb6\xce\xd4\x6e\x10\xdd\xb5\xfd\x42\xa8\x63\x87\x2f\x17\x70\xd0\xa4\xde\x39\x57\x08\x25\xa6\xe0\xa3\x72\x55\x87\xb5\x41\x27\x34\x9d\x02\xa1\xbc\xac\x7c\x8e\xb7\x9f\xe5\x15\x89\xe2\x3c\x15\x56\xc4\x3b\x0b\xa3\x9b\x55\x08\xd0\x7a\xc9\xe2\x7f\xc8\x8e\xcb\x3b\x61\x8c\x89\x8f\x26\x2c\x95\x96\x46\x88\xa8\x4d\x6e\x46\x87\x78\xb1\xec\x03\x1a\xca\x1d\x6b\x5b\x71\x9d\x5c\xc7\x3d\x40\x73\x50\x76\x9a\x7f\x78\x37\x23\x01\x79\x9b\xc2\x5a\x9f\xa4\x7d\xf2\x26\x05\xb5\x38\x42\xad\x0d\x86\xe9\xce\x96\x71\x11\xc7\xcb\xee\x4b\x9c\x7c\x97\x11\xd9\x77\xcf\xf0\x81\xe3\x83\xc2\xb2\xf8\x30\x23\x07\x29\xa8\x47\x10\xea\x37\x42\xde\x97\x56\x22\x70\x8c\xbf\x90\x33\x57\xac\xdb\x8b\x76\xa2\x2a\x5b\x25\xa5\x39\x79\xa1\x58\x8d\xe1\xe6\x6f\x02\x78\xcd\xe4\xc1\x65\x0a\xbd\x33\x67\xb8\xf9\x9b\x1a\xdf\x56\x6f\x48\x37\x94\x78\x96\xf5\xd9\x84\xaa\x1f\x02\x3c\x25\x35\x6a\x9d\xf9\x26\x30\xaa\xc4\x47\xe6\xa0\x6c\xc8\x60\xb8\xa9\x44\xaf\x52\x1e\x60\x46\x1e\x50\xc4\x60\x63\x46\xbe\xa8\x99\xb2\xaf\x5a\x24\x40\x02\x51\xe3\x9c\xf8\xc6\xd3\xdf\x44\x1d\x63\xf1\x0d\x44\xcc\x3f\x9a\xa9\xfb\x4a\x68\xb9\x15\xbe\x53\xeb\xbc\x38\xdd\x28\x84\xa4\x6d\x3b\x76\x86\x8f\x41\x38\x18\x85\xd6\x84\x82\x69\x88\x17\xb2\x95\xd7\x43\x79\xa2\xbd\xde\x66\x5e\x0f\xc5\x8f\x35\x15\x87\x4b\x4c\xa7\x04\xdc\x8a\xad\x9c\xfb\x54\xf3\x51\x00\x71\x66\x1e\x57\xd8\xca\xb2\xcd\x70\x7d\x9b\x81\x1d\x3b\x9b\x6a\x7e\x9b\xeb\x46\x63\x2a\xad\x5b\x02\x5c\x81\x21\x08\xe7\x69\x73\xa5\x32\x86\xca\x9a\x5a\x48\x56\xd7\x48\x60\x3f\x52\x05\x4a\xb1\x4e\xd3\xbf\xa0\xf0\xfe\x8e\xba\x5b\x95\xba\x5f\xdb\x4f\xc0\x9c\xec\xa5\x79\x0c\xb2\x42\xfe\xe1\x20\xe9\x48\xda\xd8\x51\x8c\xcb\x88\xae\x8f\xdf\x1a\x50\x57\xcf\x41\x21\x00\xbf\xf4\xbc\x75\xb0\x71\xd4\xdc\xf2\x47\x63\xcb\xea\xd0\x45\xad\x65\x96\x1b\x81\x34\x28\x7e\xf2\x00\xb5\x7c\xc9\x78\xe3\xa0\xc5\x8f\x45\x27\x28\x58\x54\x7c\x8d\xe3\xd1\xb9\x3a\xc3\x3b\xc0\xd5\x9f\x6b\x4a\xed\x73\x82\x8f\x3b\x14\xf0\xc5\x42\x0b\x94\x93\x00\x34\x86\xc7\x03\xff\xbc\xdd\xa3\x63\x9f\x64\xf0\x93\x4d\x14\x3b\x37\x61\xda\x6b\xb1\x26\xd1\x54\x6a\xe0\x4e\x6c\xaa\x89\xeb\x55\x18\x42\x6f\xa8\x7e\x95\xef\xa5\x26\xa1\x35\x88\xd7\x5d\x88\xd2\x7c\xa1\x26\x00\xe5\xe5\x3b\x72\x41\xab\xde\x82\xbc\xc9\x22\xb9\xe2\xff\x7b\x81\x31\xbf\x0b\xbb\xe9\xe7\x25\xa2\x20\x42\x09\xf2\x58\x8e\xd9\x59\x18\x51\x2f\xf1\x01\x07\x3b\xc4\x71\xc7\x8e\x62\xed\x91\x65\xef\x21\xe3\x2f\x36\xb4\xdf\x26\x6b\x65\xf2\xfb\xdd\x91\xd0\x8e\x17\x1c\x2f\x42\xb5\x36\xc1\x73\x56\xb2\x29\x65\x7d\x26\x6a\xc1\xdf\x70\xeb\x6e\xd5\x96\x5c\x55\x72\x6c\x83\xa2\xad\x95\x82\xc2\xbb\x8b\xe5\x6e\xfa\x45\x9e\xa1\xa2\x1f\x9d\x59\x7c\x47\xe6\x93\x5f\x22\xb8\x79\x31\x72\xe8\x74\x61\x1c\xe5\x5b\x7b\xd0\xf9\xbd\x2b\x86\xef\xfb\x21\xe8\xb5\x13\x7a\x71\x2e\x10\x2e\xe8\x08\x1b\x69\x09\x4b\x20\xe0\x2d\x7d\x86\x50\x48\x30\x20\x97\xe7\x78\xe5\x85\xb1\xde\xd9\x2b\xdb\xd3\x52\xa0\x92\x00\x10\x4c\x95\xd8\x97\x28\xb1\x4f\xbd\x4b\x00\x01\x78\x51\x48\xbf\xda\x29\x5d\xad\x4d\x80\x2e\x45\x2e\xc6\x00\x68\x97\xa8\xfe\x18\x8c\x06\x36\x92\x32\x63\xcb\x9e\x38\x73\x22\x20\x84\xa0\xed\xf6\x2c\x1e\xcd\x48\x1c\xc1\x8c\xa4\xf0\x64\x00\x18\x93\xdb\x9e\x91\x6f\x29\xbe\xd9\xdc\xd6\x6f\x16\x25\x73\xa9\xe7\x71\x6d\x27\x7d\x57\x8d\x3a\xc1\x38\xf9\x45\xae\x29\x1c\x5e\xa0\xbf\x59\x19\xf6\x8a\xd7\x4c\x7e\xfa\xe5\xb2\x57\x61\x6d\xb1\x15\x3b\x8c\x7c\x41\x11\x39\x63\x46\xe2\xd1\xfb\xd4\xfe\x9c\x82\xab\x01\x6e\x65\x5c\x81\x1e\x57\x50\xc4\xe9\x8a\xda\x75\x41\x75\xce\x74\x86\x1f\xc8\x39\x50\xda\xc4\x5d\x9e\x99\x28\x88\x3c\x72\xde\x08\xc8\x22\xe7\x40\x00\x8b\x5a\x2f\xbc\x8e\x6c\xd1\x67\x47\x68\x4c\xdf\x77\x29\x78\xb6\xc0\xb8\x62\x42\x87\x24\x03\xf7\xad\x2d\x74\x5c\x31\xd1\x67\x6a\xb4\x5e\xe4\xbc\x15\x90\x44\xce\x2b\x01\x61\xd4\x74\xe8\xe7\x24\x89\x60\x38\x18\xe2\x06\xff\xfa\x85\x3f\x9f\x3c\xd3\x7a\xb9\x5c\x4a\xc6\xd8\x58\x58\xb2\xbd\x85\xb1\x63\x4d\xbd\xed\xc7\xf8\x6b\x24\x37\x86\xb6\xc4\x6b\x3e\x2f\xd2\xb1\x65\x2b\xda\x34\x41\x47\x3d\x51\xae\x79\xbc\xa0\x10\x44\xed\x1a\x4e\xd5\xed\x13\xfc\xfc\x68\x46\x42\x05\x48\x5e\xa4\xfd\x57\x0c\x28\x85\x51\x0e\x8b\x6e\xb4\xd6\x4c\x92\xa3\xbf\x07\xd7\xb6\x1a\x4d\x31\xea\xd1\x85\xed\x6b\x02\x26\xdc\xec\x73\x51\x45\x75\x6a\xe8\xcc\xc4\xb0\xd2\x69\x1e\x24\xfd\xa3\x68\x10\x57\xe3\x58\x69\x97\x08\x16\x15\x71\x4d\xd3\x68\x7d\xfc\xc8\x6a\xea\x0b\x53\x88\x17\x8d\x51\xab\xe8\xa3\xe3\xf1\x2b\xf1\x25\x71\x66\x24\x88\xc0\xd3\xe9\x31\xc3\x80\x24\xa5\xf5\x49\x3e\xab\x1b\x92\x46\xc0\x10\x10\xfa\xec\xa8\x47\x92\x0d\x86\xd1\xe4\x81\xf5\x3d\x9a\x27\xb3\xe8\xbb\x90\x34\x47\x11\x43\xdc\xab\x6b\x79\x95\x3a\x53\xe2\xaa\xa5\xd7\xa1\x49\xd4\xa8\x9e\x17\x5e\x58\xcd\xeb\xca\xd4\x32\x3d\xcf\xcc\x46\x24\x21\xc1\xb8\x61\xf8\x61\x2d\x85\x3d\xaf\x84\x71\xe1\x18\x2f\xa1\xde\xba\x58\xe4\x0c\xc5\x33\xbd\xcc\x09\x68\xf7\xf2\x56\x73\x81\x0e\x77\x7e\xb2\x0f\x78\xca\x28\xb0\x33\x3b\x06\xb6\xa9\xa4\x1f\x26\x29\xb8\xae\x79\xef\x06\xea\x15\x97\x14\xbc\x37\xb6\x00\x77\xa2\xdf\x2f\xea\x99\x20\x34\x48\xfe\x5e\xc4\x60\xab\x18\xa2\xe2\xb9\x10\x25\x3f\xaf\xcf\xd2\xe6\x40\x27\xb5\xa3\x23\x5c\x31\xde\xf7\xde\x00\xef\xbb\x2e\x86\x63\xca\x22\x6d\x4f\x47\x21\x56\x93\x53\xf5\x51\x45\xba\x5a\x7f\x82\x9c\x2c\x8f\xe0\xf7\x7a\x8b\x67\xbf\x37\x35\x60\x1f\xf2\x06\x9b\x95\x06\x01\x89\xca\x1a\x67\xaa\xdf\x40\x3d\x6d\xc2\x39\x11\x30\xa8\x06\x5b\x69\xad\x89\x7d\x0e\x07\xc5\x02\xa8\x36\xda\x1c\x6a\x41\xe1\x8d\xd0\x96\x18\x67\xa0\x44\xb6\xc8\x59\x0a\x8a\x17\x73\x55\xe1\xef\x44\x78\x8b\x4c\x84\x37\x3f\x55\xcc\xc3\x41\x43\x20\x29\xf3\xcf\xb7\x10\x06\xd0\x90\x1a\xa5\x12\x97\xdc\x0b\x9b\x0c\x7b\x5f\x66\x24\xde\x40\x34\x82\x3d\xf9\x11\x74\x03\x8a\xb1\xca\xaf\xf0\xdb\x79\xe0\x2b\x13\xad\x69\x1a\x15\xd1\x9a\x0e\x04\x85\x77\x29\xe9\x4a\x62\x7d\x15\x49\x7c\xd1\xf1\x33\x81\x46\x0d\x1d\x9d\xac\x1c\x43\x88\x77\xa3\xb5\x16\xdf\x8c\xdb\x93\x04\xdc\x33\x3b\x46\x19\x78\x1c\x99\x08\x48\x97\x77\x36\x23\x18\x3b\x15\x05\x61\x75\x62\x74\x2e\x5d\x7b\x1c\x61\x3f\x93\x5a\x73\xd9\xe8\x72\x6c\x78\x68\x46\x98\x83\xfb\xc9\xd5\xb3\xec\xb3\x53\x14\xb7\xb3\x55\x8e\x6b\x4e\x64\x04\xa7\x29\x8a\x02\x35\xce\x4b\xf6\xd3\xbe\x7b\xf6\x3c\x76\x32\x54\x44\x2c\x05\xd8\xd5\x65\x68\xec\x49\x2a\x74\x55\xc2\xcf\xd4\x9e\x91\x6e\x04\x19\xc8\x7e\x8a\xaa\x4e\xfc\xa9\xa8\xa4\x7b\x50\xe1\x93\x4d\x66\x1a\xb4\x28\xc7\x21\xba\x07\x38\x44\x1c\x30\xfb\xff\x62\xa8\xec\xb4\x1c\x2a\x3b\xad\xf0\xe3\x6d\x43\xf5\x9c\x69\xa4\x87\x4a\x32\x3d\xb8\x34\x05\x0f\x4d\x9e\xd4\x57\x71\xcd\xed\x8f\x29\x2a\xa1\x9a\xbe\xcb\x96\xbf\x9b\x2d\x7f\x77\xcb\xae\x37\xb9\x8c\x60\x1a\x55\xda\x5c\x46\x70\x90\x96\xc3\xc1\xd6\x7a\xc1\x2f\x23\xf0\x6b\x2b\xbe\xbd\xd4\x1d\x3b\xd1\xdf\x8c\x35\xfb\x72\x52\x61\x23\x57\xaa\x5d\x46\xd0\xad\xd5\x7a\xb2\x5c\xeb\x78\xa9\xb3\xe3\xa2\xda\xd3\xd5\x6a\x45\x67\x65\xad\xdf\x6d\xed\x2a\xbb\xb2\xdf\xe7\x44\xf6\xa7\x4a\x6c\xc3\x3f\xd7\xad\xea\xb3\x3d\x5c\x03\x9c\x3f\xae\x4e\x29\x25\xa0\x9c\xb0\xc4\xe6\xef\x91\x7c\x75\xb4\x06\x5e\x68\xef\x33\xbd\x94\xfa\xb7\x29\x89\x8b\x92\x69\x04\x0d\x2a\x7e\x01\x46\x03\xbb\x0a\x55\x9e\x93\xf4\x3d\xb5\x47\x1c\x3d\x7f\xdd\x03\x5b\x38\x49\x9f\x69\x55\x7f\x71\x8b\x94\x38\xc4\xab\xc2\x93\x86\x1a\x35\x61\x25\x2a\x79\xea\xf4\x7a\xe6\x4a\x22\x3f\xc0\xcb\x1f\x2a\xee\x21\x3c\x5c\x21\xef\x86\x6a\x1b\xa8\x15\xad\x37\xd6\xd6\x1f\x47\xeb\x8a\x68\x9d\x63\x53\xd5\x85\x44\xab\xc5\x66\xe4\x43\x0a\xe8\x8a\x22\xfa\xec\x71\x11\xa2\xb8\x66\x43\x3d\xb0\x6f\x10\x61\x75\x29\xb0\xc7\xf6\x1c\x9f\x1f\x53\x70\x3f\xda\x71\x46\xac\x97\x49\x16\xf9\x9d\x38\x91\x9d\x34\x73\xc7\xa1\x44\xdd\xa5\xc2\xa9\x90\x27\x36\xee\x84\x29\x96\xcf\xb9\xec\x60\x88\xff\xbe\x95\xbb\x05\x65\xd5\x58\xc8\xb9\x71\xfa\x47\x3b\x4c\x2a\x76\xcc\xb9\x85\xfa\xe7\x0c\xde\x20\xcf\x16\xa4\x3a\x1c\x22\xbc\xc2\x13\x78\x62\xcc\xb9\x7f\xa0\x39\x37\xbe\xa8\xb8\x29\x3c\x33\x87\x7c\xeb\x81\xa3\x76\x45\xa1\x90\x7e\x77\xb4\x9b\xd8\xa5\xb9\xbe\xdc\xa8\x26\x68\xb6\x36\xbc\xca\xa9\x2e\xc7\xe4\x29\x39\xb8\x38\x25\xac\x6a\x06\xac\xbd\x13\x12\x33\xce\x39\x39\x74\x8d\xf3\x89\x7b\xad\x58\xa6\x63\x8a\x03\xbf\x4d\x1b\x1c\x21\x1a\x32\x6e\x22\x29\x2d\x73\x6e\x62\xb6\xfa\xc7\xf6\x0d\xd9\x4d\x4d\x14\x0f\x0f\xa3\xba\x0a\x04\x0b\x6f\xd7\xc6\x39\xe8\x54\x9c\x8d\x8e\x86\x02\xe6\xe4\x44\x2d\x19\xce\x5e\x8f\xf1\x3d\xae\xe5\x8a\x9b\xc5\xd6\x03\x23\x68\x8f\x54\xb3\xdd\x44\x49\xb5\x0d\x23\x44\xb6\x80\x9b\xdc\xff\x8a\x27\xd4\xd6\x8a\x2b\x63\x9e\x91\x4f\x29\xf2\xe9\xb5\x91\x8a\xbe\xfb\x71\x01\xcb\x16\xea\x27\x2e\xad\x18\xac\x68\xce\xb9\x01\x3c\xbd\x55\xf0\xdc\xd3\x60\xc8\x62\x04\x32\x3f\x4c\x27\x11\x9b\x77\x58\x10\xe8\xa8\x48\x98\x48\x3c\x5d\x0b\x8c\xd0\x02\xe2\x05\x90\x7a\xab\x1e\x0e\x7b\x1a\x48\x4b\xf0\xfc\x92\x83\x27\xba\xd7\x4c\x51\x0f\x7e\x4d\x57\x43\x69\x54\x86\xbd\xc6\x87\x54\xd5\x78\xb5\xea\xd7\xb5\xd2\x87\xda\x13\xb5\xd0\x13\x8d\xa4\x8b\x93\x19\x25\x0d\xae\x1a\x4a\x0a\x11\x65\xc5\xfe\x74\xc5\xd3\x48\x75\xe5\xe2\x9a\x3f\x86\x64\xc9\x77\x6f\x38\xb4\xb3\xd2\x65\x46\x2f\x55\x82\xd1\xc9\x57\x7c\x5c\xf0\xbe\x46\xc1\xc2\xd2\xfa\xbc\xd0\xeb\x93\x34\xb9\xdc\xe5\xee\x0b\xc5\x7c\xd1\x66\x2b\x5a\x1f\xa4\xec\xd5\xeb\xfd\xd7\xc7\xaf\x97\xe3\x94\xcd\xa3\x8a\x9b\x81\xbe\xbb\x33\x3e\x06\x37\xd1\x5f\xbb\x49\xeb\xbb\x7e\xcb\x65\xda\x2c\x02\x01\xf3\x48\x5f\x69\x5c\xff\x95\x6e\x1b\xc2\x5a\xad\xdc\xd2\x9d\x24\x04\x2f\xea\xd0\xcb\xbb\x75\x05\x2e\x74\x90\x30\xf7\x50\x7b\x57\x1c\x45\x8d\x06\xc8\x47\x4c\xe7\x5c\xc8\xdd\x64\xaf\xec\xaf\x82\xc4\x14\xd8\xdc\x8e\xc1\x3d\xd1\x17\xc3\xc7\x51\xab\xf9\xe1\x6a\x7a\x72\x2f\xcb\x2f\xea\x6b\x10\x19\x25\x35\x35\x69\x98\xd4\xb7\x39\xce\xb4\xfa\x64\x41\xe1\x75\xe4\x1c\x92\x3f\x87\xb0\x09\x83\xef\x14\xce\xda\x34\x02\x0d\xb9\xfb\x6b\xc0\x36\xb7\x67\xe4\x38\x6a\xd6\x16\xef\x71\x38\x8a\xd4\x74\x5f\x47\x74\x01\x71\xcd\x45\x77\xe5\x3c\x76\x6d\xe3\x7f\xa7\x61\xdb\x7d\x8f\x58\x6f\xae\x8f\xf9\x9c\x5c\x23\x1b\x07\x3b\xab\x53\xcf\x49\xc4\x7b\x45\xdc\x0d\x77\xde\x77\x7d\xba\xea\x7a\xab\x59\x4d\x6f\x99\x74\xe4\x8d\x2b\x5f\xd3\x94\x6f\x4e\x6e\x22\xb4\x12\xe8\x4a\x72\xac\xa4\x19\x6f\x54\xd2\x2c\x5e\xa5\x59\x16\xb5\x77\x93\x92\xe4\x6d\x17\x87\x7d\xe9\xb4\x86\xc8\xa9\x30\x64\x5c\x3c\xed\xdd\x76\xcd\x20\xe9\x7b\x14\xd5\x13\xdc\xad\x75\x0a\xe8\xe8\x16\xe6\x8e\x6e\x9e\xc3\x56\x1c\xdd\x12\x0a\xde\x77\x4a\xed\x06\x24\x10\x2e\x30\xd6\x66\xf3\x51\xaf\x3a\xe5\xa1\x7b\x77\xb4\xc6\xe0\xaa\x7d\xf7\x57\x50\xe8\xf0\x4e\x14\xba\xbd\xba\x6b\xe8\x65\xbd\x8a\x63\xab\xb4\xb0\x82\x6d\xdd\x0f\x36\x9a\x9e\xe8\x36\x76\x95\x1c\xa8\x32\x2f\x23\xdc\x10\xc5\x1c\xfb\x1d\x33\x4d\x14\xa4\x22\x0a\x3c\x27\x0a\x28\x8a\x57\x95\xfb\x59\x83\x1f\x9d\x1a\xdd\x10\xc1\xef\x24\x05\x09\x19\xbc\x66\x15\xf4\xb9\xae\x45\xb9\x47\xcb\xbc\x4d\xa6\x3d\xdd\xde\xae\x4d\xa9\xcc\x0e\xed\x18\xd8\x17\x5b\x82\xfb\xcd\xe6\xe0\x76\x35\xa6\x78\x65\x6c\x3d\x12\x11\x5e\x84\x31\x8b\xd6\x25\xf5\x15\xc6\xb4\xe2\x85\x68\x4f\xc1\xa1\xed\x53\x52\xf5\x99\x23\x93\x93\xbb\x55\x85\xba\x6b\x0b\x30\x99\x82\xe1\x8d\x19\x07\xf3\x7d\xc1\xd3\xb4\xdd\x3e\x45\xab\x20\xd6\x5b\xa4\x08\xce\xfc\x79\x93\x3d\x4a\xca\xa5\x8c\x6a\x66\x27\xb9\x45\x8a\x1f\xa6\xcc\x8d\xfe\xa5\x04\xcc\x67\xda\x1c\x67\xc2\xb5\xf5\x87\x20\x27\x09\x79\xa3\x64\x94\x3c\xcd\x4b\x6e\x7a\x72\x20\x74\x4e\x18\x3d\xb9\x32\x17\x4c\xca\xc9\x0b\xa1\x13\x2d\x8b\x3b\x8c\x2f\x7e\xb2\x8f\xb6\x04\xf6\xc9\xce\x80\x7d\xb6\x39\xb0\x67\x36\x03\x17\xf5\x67\xe7\x7a\x49\x0f\xcc\x92\x5e\x24\x27\x5c\xa4\x61\x12\x97\x8b\xea\x66\x61\xe4\xbf\x42\xeb\x9e\xa5\x57\x5f\x52\x2e\x2a\xaf\x04\x8b\xbd\xcb\x6a\xc2\x9b\x69\xb8\xdc\xcf\xb4\xd2\x71\xca\x71\xae\xda\xc6\xe5\x65\x94\x5b\xdf\xc8\x50\x4d\xf1\x20\x37\xaf\x89\x83\xf0\xc2\x82\x57\x62\xa9\xfd\xbb\x38\x48\x70\x51\x74\xa5\x28\x4b\x31\x8a\xdc\x99\xea\xf3\xad\xc9\x3c\x7d\x1e\xdd\xc3\x1f\x27\xe7\x0e\xb4\xd7\xfa\xa7\x00\x62\x78\x19\x2d\xd3\x65\xa1\xe8\xb2\xb6\x06\xdf\x8b\xd6\x5d\x81\x69\x01\xe0\x3c\x82\x82\xc1\x3e\x63\xf0\x45\x31\xd8\x39\x82\x70\x8f\xec\x9f\x2e\x3a\xbe\x2c\x0c\xda\xa3\xb0\x1f\xb5\x87\xfd\x7b\xa6\x83\x1e\x3d\x59\xbd\xaa\x7c\x62\xb0\xc5\x94\xec\xba\x70\xa4\x0e\xb9\xfb\xd8\xb0\xf6\x1c\x24\xd5\x71\xa8\xea\x58\xe1\x31\x32\x65\xde\xcc\xf6\xc0\x3b\xb5\x5f\x71\xe2\xd1\x8a\x38\x33\xd4\xe4\xc9\x83\xc4\x99\x92\xb3\x08\x8e\x11\x75\x0c\x4c\xaf\x0a\x33\x68\xb2\x51\xf7\x37\x35\xdd\x7d\x56\xdd\x81\x37\xd0\xd7\x40\x1a\xe9\x1d\x70\x60\xab\x36\xa9\x79\xc3\x53\xfb\xa5\x66\x0e\x0b\x09\xe0\x8b\xf6\x51\xcd\x5d\x54\x6b\x0a\x04\x74\x65\x76\xe6\xe4\x2a\x02\x13\xaa\x3c\x59\xa8\x21\x0e\xf5\xd0\xc2\xd5\xa1\x9d\xda\xef\x39\x51\xe4\x69\x68\x87\xe5\xa8\x3e\x54\x47\x35\xb0\xc3\x06\x04\xea\x9d\xda\x3f\x38\x09\x69\x3e\x3c\xdc\xcd\xd7\x98\xfd\xf6\x5a\xcb\x71\x57\xaa\x78\x59\xbc\x0c\x9a\x3b\x7a\xc1\x49\x40\x97\xe7\xf9\x86\x93\xb7\xea\x6d\xa3\x57\x7c\xde\xee\x6c\x99\x79\xdf\x6e\xf6\x82\x8f\x4b\x36\x6c\xb8\x24\xee\xed\x25\xa4\x5a\xd6\xe2\xa8\x2f\x2b\xc1\x26\x56\x8d\x8f\xcb\xc1\x5c\x25\x8d\xf4\x73\x46\xf6\x8c\x24\x51\x10\xce\x40\xc3\xa4\xe6\x38\xdc\xc7\xea\x33\xb3\x1c\x26\x83\x26\x98\xc4\xeb\xb9\x02\x0a\x35\x19\x74\x35\x08\xea\x4e\xbc\x81\xee\xc4\x80\xa0\xbb\xba\xcf\x03\xdb\x6d\x06\xba\xc7\xb6\xab\x8e\x75\x3e\x1c\xef\xac\xa5\x83\x33\xd3\x01\x5b\xe2\xd4\x52\x0d\x6c\xa6\xad\x01\xb3\x74\xb5\xf5\xd0\x4e\x9b\xa1\x6b\xd3\x4e\x9d\x1b\x72\x51\x74\xd1\xcd\xe7\xd0\xd0\x49\xd7\x74\x52\x0c\x61\x05\x24\xdc\x15\x46\xe7\xf7\x7a\x95\xf9\x4a\x95\xba\x07\xbf\x17\xd7\xab\x6c\xd6\x79\x58\xef\xba\x52\xa5\x45\x4a\xfb\xb1\xcc\xba\x7d\x8c\xd6\x67\x65\x9c\xd9\x1c\x6e\x6d\x09\x99\x4e\xb5\x95\xc1\x8e\xa6\x38\xbb\x51\xb3\x7f\x9e\xfb\xf0\x21\xb1\x2c\xcd\x7b\x69\x6d\xa0\x9b\xe7\x49\xe8\x33\xd8\x8d\x50\x3d\x42\xed\xd3\x05\x9c\xb6\xa2\xe4\x6b\x99\xdf\x1c\x8e\x74\x10\x5d\x3b\x4f\xb4\x60\x42\x1c\xbf\x5b\xfe\xb8\x14\xf3\x4a\x53\x9f\x37\x24\x15\xa3\x0b\x8f\x19\xb6\xa1\xc8\xe0\xb4\x58\xc0\xa7\x36\x14\xae\xe3\xc9\x3a\x96\x49\x79\x27\xd5\xbc\xa4\x8e\x25\xf8\x40\xe6\x81\x04\x63\x47\x3d\x32\x90\xce\xbb\x08\xaf\x98\xf3\xbb\xb9\x4a\x02\x45\xf1\x5c\xa2\xff\x7a\xac\xea\xc4\x4b\x97\x6f\xda\xf8\x42\xc7\x11\x86\xd3\x48\x47\x54\xa9\xe6\x26\xa0\x70\xd8\xba\x46\x2d\x91\xdf\x1f\xc4\xa5\x03\xbd\xc9\x51\xb5\x9c\x7d\x40\xf4\xb3\x3c\xa8\x23\x2d\xd7\x0c\xaf\x36\x9e\xe7\x61\xce\x78\x9f\x3d\x7c\xb8\x1c\xf8\xad\xa8\x13\x3b\x72\xb1\x20\x31\x99\x92\x8f\x11\x9c\xae\x38\x48\xbe\xd4\x34\xba\x9c\xa8\xde\xf1\x87\x0f\x75\x60\xb3\x3e\x1b\xc5\x7d\xd7\x8e\xe9\x42\xc9\x92\x19\x05\xb5\x0e\x04\xb3\x71\x1f\xd3\x7e\x77\xd4\x4d\x6c\x0c\x3c\xf0\x29\x82\x6e\x62\x82\xfa\x3e\xb4\x34\xaa\x54\xbb\xff\x04\x98\xd4\xb2\xf5\x49\x74\x2f\xa3\xec\x4b\xc5\x38\x31\x05\xbb\xb7\x36\x87\x43\x3b\x81\x23\x9b\xc1\xb1\xed\xc1\x17\x3b\x83\x5d\x0d\xcb\xb7\xd1\x5f\x48\xb4\x26\x49\x11\x07\x98\x07\x46\xd7\x8c\xdc\xf5\x1a\x75\xc7\xc7\x08\x44\x7f\x07\x44\x3f\x03\xd1\xbf\x05\xd1\x9f\x41\x7e\x9d\x84\x79\x0f\xa3\xa5\x54\xf0\x45\x22\xf8\xf6\x04\xe7\x71\x7f\x07\x77\x34\x43\x3b\xfa\x5b\x34\xa3\x9f\x3d\xaf\x8a\xce\xaf\x70\xdd\xcf\x28\x78\x7a\xab\x4a\xa6\x52\x0f\xb7\x39\x77\xe4\x8c\xdc\x46\xe8\x50\x73\x9e\xc0\x69\x06\x07\x21\xc1\xc7\x2b\x06\xf3\x90\x58\x01\x8b\x52\x6e\x69\xd5\x3a\xbc\x8d\xd6\x04\xd1\x68\xcc\x5f\x5f\x7c\xe3\x30\x51\x64\x05\x4f\xe5\xda\x0b\xe5\x19\x79\xab\x46\x43\xa4\x23\x1a\x6f\x31\x6f\x2b\xf1\x40\x71\x92\x6a\x59\xd4\xa2\x08\x88\xfb\x33\x20\x78\x7b\x7a\x46\x09\x1a\xf8\xd0\xef\x68\x68\x92\xfb\x93\xbf\xa9\xcc\xdf\x5b\x93\xc9\xae\x71\xa5\xb5\xbf\xc2\x99\xc1\x0c\x1a\x11\x60\xea\xbe\x92\x38\x5c\x90\x18\x3c\x3a\xca\x47\x56\x64\x8a\x29\xb6\xe1\xbb\x42\x82\x45\xbc\xcf\x05\x1c\xac\xd9\x8f\xc6\xfc\x2c\xae\x41\xaf\x79\xae\x45\x14\x59\x17\x4a\xca\x9b\x91\x2b\x38\x51\xdf\x7c\x21\xee\xf3\xcf\x1b\x41\xf2\xb0\xed\x14\x0e\x8a\xc8\xce\x14\x7f\xe8\x00\xce\x78\xe1\x72\x1b\xc1\x4a\x08\xe7\x1c\x52\xe6\x98\x6e\x94\xea\x36\x45\x20\x68\xaa\xe0\xac\x12\xac\xda\xfc\x2e\x23\x53\x9b\x17\x3a\x10\xb5\xf9\x61\x1c\x09\x8c\xfc\xa7\x06\xa7\x44\xb9\x30\xbe\x50\xc3\xab\xe5\x34\x4c\xfe\xd5\x9d\xd3\x27\x4d\x23\x68\x4c\xf4\xea\x24\xc4\x33\x28\xbf\xc0\xe1\xa7\x1a\x87\xd7\xa1\xcd\x44\x7f\x15\x14\x62\xbd\xa7\x44\x22\x94\x95\x9b\xaa\xc4\xc4\x99\x92\x73\x8e\x8e\x0f\xdf\x7d\x7c\x6b\xc1\xb5\x44\xd9\x1d\x01\xfb\x4d\xb9\x32\x6a\x66\xf8\xee\x0c\xdf\x72\x3f\xd4\xf7\xd9\x27\x62\x39\x4b\x6b\x5c\x5a\x91\xc6\x90\x39\x72\xed\x29\x13\x80\xde\x44\x59\x7e\xce\xc2\x35\x0e\xfd\xf9\x15\x9a\xa0\xe0\x5e\x2b\x14\x9c\x80\x70\xc9\x38\xa0\x30\x09\xc8\x29\x35\x19\x25\xc3\x96\x81\x1b\x18\x8a\xf9\xcc\x42\x5d\x87\x80\xb0\x0a\x47\xea\x39\x77\xb6\xd0\x20\x82\x10\xda\x30\xe8\x94\x9c\x28\x70\xdf\x91\xf0\x60\xa8\xfe\xad\xfc\x1f\x33\x41\x99\x0f\x55\x3e\x5e\x05\x57\xbd\xda\xab\x03\x3c\xc3\xd3\x8e\x2f\xb5\xd0\x48\xe1\x4d\xe4\x90\x2c\x71\x50\x19\x76\x05\x9f\x39\x1c\xa8\x79\x5c\xc1\xcb\x04\x4d\x27\xd4\xe3\x55\x02\x07\xe6\xf1\x07\x87\x50\x3f\xbd\xe7\x70\xa6\x9f\x5e\x70\x78\x6b\x8a\x5f\x71\x78\x65\x1e\x75\x50\xc4\x86\x99\x69\x3e\x66\x41\xbf\xd3\x26\xbb\x09\x44\x89\x4d\xec\x14\x9a\xc6\x64\x28\x6d\x1e\x44\xce\x0f\x01\x1f\x22\x13\x78\xf1\x8b\x36\x5e\xd8\x5a\xc0\x0b\xfd\xb4\xb9\x80\x1f\xfa\xe9\xc9\x02\x3e\x47\xf7\xc9\x41\x75\xd5\x62\xa3\x3c\x06\xee\xbc\x64\x3a\x28\xed\x8c\x7c\x8e\xb4\x8d\x92\x9b\xe8\xd4\xbb\xd6\x44\x24\x7e\x86\x8d\x2c\x08\x12\x0c\xcd\xa6\xa4\xd6\x91\xa2\xe8\xb6\xa2\xfe\x5e\x53\xab\x8b\x5a\x36\x81\xbc\x65\xe2\xe4\x71\x91\x1c\x47\xb7\xcb\x7f\x57\x5b\x07\xb5\x30\x4e\x3b\xba\xf5\x68\x68\x0f\x20\x6c\x88\xd9\xc4\x2b\x96\x17\x35\xef\xe8\x95\x84\x1a\x9d\xeb\xc4\xc4\x68\xd2\x9f\x5f\xfa\xb0\x5f\xf3\x96\x31\x1f\x86\xcc\xb9\xe5\x24\x9f\xf3\xa5\x94\x13\xfb\xd1\xa3\x28\xf1\x58\x74\x99\xa4\xd2\x7e\x36\x78\xb6\xf5\xc8\xaa\x6a\x23\x22\x38\xd7\x6e\xde\x63\xe7\xa7\xbe\x85\x3b\xc5\x3b\x35\x59\x6a\xaa\xa3\x04\xdc\x13\x7b\x58\x81\x9f\xee\x2a\x7a\x9b\xae\xbe\xf2\x57\x5f\x45\xab\xaf\xd2\xd5\x57\xee\xea\xab\x60\xf5\x55\xb8\xfa\xaa\x01\xed\x36\xd0\x50\xb6\xfa\x2a\x5b\x7d\xd5\x90\x46\xb6\x81\xff\x12\x6b\x58\x32\x25\x8a\xfa\xe0\x3e\xb1\x43\x70\x9f\xd9\x01\x78\xae\xed\x81\x77\x6d\x73\xf0\x62\x3b\x03\xef\x87\x2d\xc1\x9b\xd9\x29\x78\x73\x9b\xe1\x3d\x26\x78\xef\xec\x04\xbc\x53\x3b\x02\xef\xcc\x8e\xc1\xeb\xda\x53\xf0\x06\xf6\x18\xbc\xa1\xdd\x05\xf7\xc8\x76\x17\xf5\xff\x2d\x5f\xa4\xe6\x3b\xf7\x60\x08\xee\x07\xbc\xad\x23\x33\x72\x91\x60\xf8\x3f\xf5\x78\xa9\x1e\x3d\x4a\x09\xa7\x24\xa4\x64\x96\x50\xcd\xf0\x92\x8c\x12\x46\x49\x98\x94\xff\xc5\x94\x78\x94\x48\x4a\x7e\x7a\x37\x76\xb2\xd0\xec\xed\x0f\xe1\xdc\xc6\x0a\x44\xde\xb7\x9e\xe4\x52\x84\x10\x1b\xc4\xb2\xad\x8d\xb3\x22\x8d\x10\x7c\x5d\x67\x2f\x6b\x44\x2b\x69\xef\x12\x09\xbb\xa4\x14\xab\xbe\x45\xed\x9c\x58\xa2\xa8\xcf\xa9\x6b\xa2\x12\xc5\xbe\xf3\x2d\x22\x96\x17\xb1\x34\xfd\xc8\xc6\xdc\xa2\x20\xfc\xdc\x29\xcb\xbd\x56\xe2\x9d\xf4\x9d\x6f\x31\xb1\xfc\x70\x6a\x51\xe0\xfa\x47\x3a\x61\xb1\x45\x21\xf3\x9d\xaf\x31\x30\xdf\x99\x11\xe9\xc3\x29\x20\x1a\xe6\xe6\x29\xf3\x89\xb5\x9f\x30\x3f\x8c\x2f\xfa\xfd\xbe\x45\xbf\xeb\x70\x36\x9e\xef\x08\x01\x89\xdf\x12\x15\x26\xf9\x32\x99\x70\xf1\x92\xa5\x9c\xd0\x05\x84\xfe\x5f\xb8\x13\xd3\x17\x62\xb9\xf6\x60\xf9\x12\x81\xf9\x75\x5c\xf1\x89\x15\xb7\x60\x81\x9e\x94\x9b\x49\x99\xa8\x69\xb9\xfe\x3d\x03\x29\xa5\xba\x61\x68\x51\x88\x7c\x87\x09\xf0\xfd\xf6\x85\x8f\x7c\x88\xc1\xf4\x20\xd0\xde\x6c\xea\x3b\x9e\x80\xae\xdf\xb0\xc5\xb1\x13\x8f\xac\x80\xf5\xc6\x61\x9c\xa5\x96\xad\x1e\x27\x51\x96\x5a\x25\x22\x0a\x7c\xb5\xc8\x27\x88\x8b\x62\x9f\x58\xae\x8c\x3b\xae\x8c\x7b\x49\x26\xa3\x30\xe6\xbd\x30\x0e\x92\x8e\x9b\x08\x9f\x8b\xde\xa0\x33\x16\xbd\x61\x67\xec\xf6\x86\x48\xe7\xa7\x3e\x58\x63\x26\x2e\xc2\xb8\x17\xf1\x40\x5a\x60\xf5\xb6\x04\x1f\xab\x3d\xd2\x7b\x98\x62\xe7\xaa\xdb\x80\xa1\xb2\x1c\x3f\x31\x16\xbd\x4d\xac\x73\xaa\xb6\x5e\xf1\x5d\x89\x31\xf4\x1b\x6b\x30\x92\xa1\x8c\x14\x08\x5d\xea\x75\xc9\x22\x8b\xc2\x44\x3f\x33\x8b\xc2\x85\xaf\xad\x00\x5b\x97\xe8\x98\xe7\x61\xea\x5a\xab\xfc\x08\x4c\x15\x72\x48\xfe\xcc\xf1\xb5\x05\xf8\x94\xaa\xc7\xef\x68\x54\xe4\xaf\x4d\xcc\x13\x57\x33\x41\x98\xd0\x1f\xda\x83\x19\x8c\x3d\x89\x73\xe1\x93\x0c\xb3\x85\x8c\xf4\x31\x63\xfd\xee\x88\xa0\x37\x47\x91\xd2\x2d\x76\x4c\xe2\x80\x99\x24\x18\xb3\x33\x91\x30\x96\x44\x6e\x58\x1d\x75\x52\x28\xc5\x54\xc8\x8d\x75\xb0\x86\x68\xaa\x21\x28\xe6\x0d\xa9\x7e\xb5\xf6\xb5\xb1\x24\xf9\x40\x74\x66\xaa\x0c\x3f\x56\xe9\x49\x7f\x60\xc3\xf4\xb6\xf4\x5e\xbf\xc3\x90\xec\x8d\x27\xf0\x90\xe4\x91\x99\xfa\xe9\x24\x0a\x25\x79\xf4\xcf\x74\xe3\xd1\x85\x92\x13\x6f\xcc\x1e\x33\x71\xc1\xa5\x45\xe1\x5a\x6f\xac\xf4\x2d\x0a\x3b\xe6\xf9\xd2\xa2\x70\x64\x9e\x15\xc3\x78\xec\xb7\x5f\x9c\xc7\xe8\xb0\xd1\x67\x43\x4a\x47\x15\x70\xde\x91\xf7\x81\xe7\x5c\xb6\x68\x04\xd8\xfc\xdc\x74\x6a\x00\x6b\xe1\x9d\x85\x02\x59\x3b\xff\xe0\x9d\x5f\xb2\x28\x9c\x30\x52\x8c\xb4\xed\x7b\xea\x70\xb6\x7f\x6e\x41\xe1\xb5\x5e\x95\x48\xe1\x8a\xb3\xa5\x55\xe1\x50\x48\x3a\xed\x99\x17\x44\x35\xf3\x82\x12\x07\x46\xe7\x79\xde\x5d\xcc\xbc\x66\x9f\x63\xe4\x0d\x23\x9b\x56\x72\xad\xa0\x16\x46\xc0\x39\x39\x05\xcd\xfe\x53\xb8\x5a\x7b\x38\xea\xa9\x20\xe3\xc2\x8f\xc9\x7f\x8e\x97\x37\xbe\xf6\x27\xe8\x73\x9a\xa7\xac\x7a\x69\x76\x9c\xb9\x78\xfa\xcf\x7d\x47\x32\xd8\xf3\xdb\x1c\xe7\x20\x76\x76\x09\xe1\xce\x8c\x9c\xf9\x26\xe6\xa9\x84\xcf\x92\x54\x12\xc9\xd0\x6a\x00\xf4\x56\x5c\xf0\xb9\xc0\x05\x31\xc5\x28\xe8\x2e\xe6\xc3\x08\x95\x6c\x82\x2e\xcb\x6e\x85\x71\x7b\xed\xeb\x9d\x53\xb8\x6f\x92\xa4\xa1\x66\x7b\x51\x92\x08\x3d\x4b\xc3\x1c\x8b\xc2\x8b\xb8\x17\x4a\x3e\x4e\x7b\xe8\x22\xde\x89\xc2\x54\xf6\x74\xa8\x7c\xf5\xba\x04\xc0\x89\x42\xaa\x6e\x6f\xbb\x04\x41\x59\x80\xc4\xac\x37\x1c\x60\xe9\x66\xc7\xef\x05\x11\xbf\xe9\xac\x74\x9c\x37\xfb\xa1\x64\x4d\x18\xfc\xf1\x02\x2d\x10\xdf\xab\x93\xe0\xf9\x4d\x12\x84\xc8\xc8\xcf\xae\xfd\x0c\x73\xa2\xa1\x08\x75\xec\xeb\x48\x29\xb6\x82\x34\x8b\x02\xc1\xf0\x9a\x4f\x69\xbf\x3b\xd2\x6f\xec\x37\x4c\x5b\xfd\x7f\xc1\x6f\x9c\x66\x6a\x6d\x8e\xfa\x2e\xaf\x54\x41\x6a\xdd\x72\x0c\x7c\x16\x5f\x70\x51\x39\x08\x6d\xb0\xcf\xe7\xbc\x97\x46\x2c\xbd\x6c\x38\x00\x85\x7e\x40\x91\xfe\x62\x08\xf1\xbf\x7b\x08\x2e\x8f\xa2\x96\x31\x7c\xc8\x8a\xef\x2f\xeb\x38\x8b\x5b\x97\x91\x16\x3c\x1d\x6b\xe3\x43\x48\x3e\x64\xab\xc6\xf6\xa5\x5f\x73\x88\xca\xef\x81\xc9\xe0\xe5\x2a\x3e\x4d\x83\x5b\x25\x75\xe0\xbd\xf1\xca\x2d\xc3\xe8\xaf\xcd\x33\x8a\xc2\xf8\x7a\x65\x2e\xfb\x61\x7c\xad\x11\x0a\xc1\x24\x5b\x70\x41\x04\xfa\xb9\xe5\x58\xf4\x65\xd1\x0b\x1e\xc6\x4e\x01\x89\x43\xec\x06\x67\xf6\x96\xe9\x73\xc2\xde\xd3\x12\x7a\x0c\x03\xa7\x23\xe9\xa3\xef\x88\x46\x5b\xfb\xfe\x9a\x34\xbf\x45\xfe\x9d\x51\xbb\x7f\x82\xb6\x0e\x2e\x97\x47\x56\x97\x47\x9f\xac\x2a\x73\x92\x2f\xc7\x32\x4c\x48\x7e\x23\x7b\x46\xb7\x64\xd8\x97\x2c\xe5\xa2\x97\xf2\x88\x7b\x8a\x7d\x09\xe3\x50\x86\x2c\x2a\x4a\x7b\xe3\xe4\xb6\x77\x47\x95\x19\x77\xaf\x43\x79\x47\x2d\xb3\x5d\x5e\x12\x29\x99\xd1\xfa\xaf\xc7\xae\x37\xf0\x0b\xba\x93\xf9\x44\x6c\xfc\xc3\xb1\xfe\xb1\x11\x6f\xfc\xc3\xfa\x07\x6e\xc9\x5d\x94\x45\x13\x94\x43\x46\xce\x89\xd6\x39\xc3\xd8\x27\xd6\x1b\x04\xc1\x8e\x3b\xef\xc8\xcb\x30\xed\x44\xcc\xe5\x51\xe5\x2b\xd6\x46\xce\x3f\x2f\x80\x53\xbb\x61\x89\xd4\x67\x52\xee\x25\xb1\xcf\xc4\x7c\x75\x45\x55\x1f\x1f\x13\xd9\xc1\x05\x37\xe7\xe1\xbb\x42\xe0\xde\xaf\x5f\x18\x21\x1a\x63\xe0\x30\x67\x3d\xfa\x19\x0e\x72\xfc\x33\x27\x5d\x85\x7f\x18\x5a\x24\x49\xe7\xab\x20\x18\x31\x0a\xef\x4c\x46\x67\x92\x48\xc5\x9a\xe0\xf1\xb2\xec\xa5\x9f\xa9\x05\xd2\xa9\x8d\x7f\x1c\xe9\xd1\x0e\x8a\x65\x9f\x5d\x86\x92\xf7\xd2\x09\xf3\xb8\x05\x56\x9c\xcc\x04\x9b\x54\xa6\x22\xf5\xf0\x97\xa0\xea\xb4\x8e\x85\xc7\x6e\x6f\xcb\x40\x7d\x22\x81\xc1\x2e\x49\x74\x14\x1d\x31\x9a\x91\xcb\xa2\x5a\x89\xe1\xcd\x10\xf2\x73\x32\x23\x7b\x3e\x60\x72\xd3\xac\x38\x27\xfa\x50\x7c\xf4\xdb\x6f\x08\x30\xf7\xad\x3a\x27\xd3\x04\xa6\xda\x72\xd3\xaf\x9a\xf8\xe8\xe3\xa3\x7d\xa3\x62\x93\x8b\x2b\xae\x5e\xd0\x54\xa7\x30\x89\x7a\x8f\xcd\x80\x76\x65\x1b\x1d\x74\xc9\xbe\x8f\xa7\x12\x93\x14\xba\x78\xbf\x13\xe2\x25\xcb\x1e\x66\xe5\x5f\xa0\x9e\xa3\x62\xb1\xef\xde\x22\x97\xcb\xb0\x82\x83\x48\x8c\xa9\x26\xcf\x97\x3b\x9c\x91\x8f\x3e\x86\xa6\x52\x44\x16\x14\xd6\xcb\x0a\x95\xe8\x27\xa6\xc0\x49\xef\xa8\x86\xa9\xb4\x13\x24\x59\xec\xa3\x41\xb9\x27\xee\x10\x3f\xdf\x07\x46\xfc\x3c\x55\x12\x10\xb1\xbc\x4b\xee\x5d\xe3\xe1\x7e\x67\x24\xaa\x78\x92\x29\x1e\xf3\x93\xe1\x9a\xf4\x71\x80\x43\xbf\xb4\x2a\x35\x7c\x28\x14\x8d\xbf\x53\x54\x45\x9d\x18\x36\x75\x3e\x51\xbc\xc8\xad\xdf\x2e\x3f\xe7\x3c\x81\x5a\xe9\x98\x4d\x91\x3c\x97\x18\xe8\x53\x09\x48\x52\x81\xa7\x82\x51\xad\x34\xef\x79\x49\x2c\x45\x12\x15\x3f\xd5\x00\xdc\xe4\xa6\x6c\xfb\x4e\x33\xb3\xbe\x99\x19\x96\x21\x83\xb1\xdc\x41\x2f\x9f\xe6\xa9\x5f\xe6\x7d\xa4\x14\x3e\x33\x7d\x5b\x23\x41\x64\xd4\xa0\xff\xea\x79\x59\xe9\xc5\x0f\x3d\x54\x6a\xdd\x5d\xd7\xe7\xa9\x27\xc2\x09\x32\x3f\xe5\x79\x8a\x0d\x72\xd1\xe0\xfd\xca\x5f\xef\x7f\xd9\xbe\x6a\x26\xc7\x51\xf5\xfb\xaa\x0a\xd2\xb2\x0a\xc7\xce\x4b\xfe\xdb\x60\x59\xe6\x5d\x2b\x28\x8a\x7d\x0b\x2c\x29\x58\x9c\x4e\x98\x40\x2d\xb3\xc1\x07\x41\x12\x6b\xec\x7c\xc9\x45\x58\xbe\xf6\x32\x91\x22\x5e\x9e\x24\x61\xac\x55\xd4\xba\xc0\x20\x5c\xc4\x1d\x31\x37\x8b\x9f\x0f\x45\x63\x60\xbc\xb6\xc2\xc1\xe8\x59\xbf\xf5\xef\x19\x97\xf8\x8d\x86\xd9\xc2\xf4\x8c\xc2\x81\xef\xfc\x83\xc7\x53\xa7\xaa\x50\xfd\x07\x7c\xd0\x80\x18\xaa\x1a\x5f\x7c\xe7\x77\x78\xe1\x3b\xc3\x2d\xf8\x81\x42\xb0\xd4\xac\xed\xb5\x84\xae\x44\x77\x77\xf8\x7c\x0f\xd5\xc1\xb0\x50\x1d\xbc\x6f\x3a\x09\x3a\x4a\x94\xb1\xb3\xfe\xaa\x6a\xa4\x09\x58\xd7\x7c\xfe\x32\xf1\xb9\x05\x18\x29\x1e\x4f\xa7\x71\x33\xf4\x0b\x9f\xc0\x6e\x50\xf5\x0b\x4c\x82\xd2\x73\xef\x9b\x5f\x78\xee\x79\x42\xa7\x98\x8e\xa7\x5a\x07\x34\x66\x91\x3a\x94\x62\x8a\xf3\xd4\x1f\xa7\x20\xa7\xad\xd1\xc2\xbc\x73\x2d\x39\x5f\xeb\xb8\x38\x57\x98\x44\x95\xed\x83\xe7\x7c\x53\xd2\x36\x24\xce\x09\xd3\x07\x21\x33\x91\x90\x5d\x1f\x83\x62\x79\x0a\x6d\x87\xce\x0f\x9f\x70\x0a\x81\x73\x41\x3c\x5c\x32\x93\xe5\xe4\x1b\x03\x94\x45\x4c\x56\x19\xcb\xb2\xbd\x7e\x77\x64\x5d\xb2\xd4\x30\x90\x96\x8d\x3f\xd2\xcc\xf3\x78\x5a\xd5\xa1\x94\x98\x56\x24\xb3\x4e\x9c\xf4\x2e\x32\x29\xb9\x48\x5b\xf8\xf5\x5d\xcd\x1a\x32\x4f\x7d\xaf\x46\x6d\xbc\x24\xea\x58\x1b\xa2\xd0\xae\x84\x71\x6f\x16\xfa\xf2\xd2\x02\x39\xb2\xb6\x06\x83\xc9\x8d\x65\x5b\x9b\xf8\xb7\x41\x62\x68\xfc\xbc\x3a\xb3\x3c\x96\xbd\x54\x0a\x2e\xbd\xcb\xa6\x76\xea\xab\x88\x44\x7a\xe6\x7a\x6f\x19\x03\x7d\xf0\x9b\xd3\x8a\xe2\x71\x08\x12\x51\xe0\x05\xdc\x46\x4c\xba\xe5\x91\x9a\x03\xaf\x3a\xd3\x2f\xfc\x8a\xab\x73\xe3\xf6\xe4\xe9\xd3\xbe\xf8\xd4\x64\x59\x7b\xe0\x38\x59\xde\xe8\x3d\x53\xf5\x9e\xc7\xce\x39\x61\x10\x56\x5c\x07\x8d\x65\x49\x77\x94\xb9\xf6\x8c\xbc\xf5\xe1\x01\xf2\xd6\x7d\x56\x50\x9a\xcc\x5d\x50\xc8\x3c\xd2\x92\xf7\xf8\x8b\x4f\x47\xaa\xf7\x21\xb5\xb1\xa6\xf4\xc8\x57\xd6\x80\x06\x2b\x8b\xd4\x73\x65\x5c\x2e\xd4\x2a\xb3\x36\x11\xe1\x98\x89\xb9\xa5\x4e\x3a\x09\x28\x24\x0d\x5c\x98\x62\xf4\xe4\xa8\xbe\x13\x5e\x12\xf5\x58\x26\x93\x4e\xed\x6b\x8a\x78\x6c\x36\x6d\x5f\xe3\xd6\x4d\xee\x62\x1f\x95\xdc\xe0\x19\xec\x75\x87\x34\xd4\x4b\x56\x64\x08\xe3\x7e\x53\x99\x49\xc9\xdb\xc0\x8c\xc4\xd3\xa2\x2f\x05\x1f\x8a\xf3\x5e\x62\xbf\xcb\xc5\x78\x89\x94\xa5\x63\x80\x0a\x3a\xbc\x7f\xd1\xb7\x9a\xf9\x5f\x24\x00\xc8\xa1\x8e\x0d\x6c\xbb\x2c\xe5\x88\xa1\x11\x17\x7f\x65\xe4\xc0\xa7\x65\xdf\x07\x7e\x39\x3a\x93\x1e\x83\x4f\xef\xa9\x93\xcd\xa6\x0d\x36\xa7\xb9\xb6\x89\xd2\x51\x11\xdf\xce\x5a\x51\xa6\xaa\x21\xfb\x22\x99\xf8\xc9\x4c\x1f\x7e\xad\xfa\x44\xa4\xc4\xa7\x18\xac\xa0\x32\x48\x61\x08\x07\x9b\xae\x63\x31\x4a\x36\x22\x78\xd2\xf1\x43\xb7\x33\x76\x37\x3b\x63\xd1\xa8\x19\xf0\xb8\x26\x62\x6b\xd9\x88\x53\xf5\x65\xc5\x22\xc8\x06\x30\x9f\x54\x00\x4d\xed\x11\x4e\xa0\x20\xec\xde\xf4\x9e\x24\x2e\x99\x3a\xbf\x43\x38\x75\xb6\x07\x10\x4c\x15\xd1\x72\xa7\xce\xd6\xef\x90\x4e\xef\x99\xee\x3c\xb7\x58\x2a\xf2\x9d\x5f\xe8\x54\xa3\x05\x16\x39\xcd\x88\xa4\xd5\xac\xe7\xd1\x74\x25\xeb\x79\x4e\x35\xd8\x39\xde\xfb\xbb\x11\x6a\x68\xdd\x31\x32\xaf\xde\x54\x1b\xc5\xee\xa3\xcb\xc4\x24\x00\x4d\x1b\x74\x3c\xcf\x36\x32\x9a\x4e\x73\x7d\xd1\x3b\x89\x01\x6f\x33\x34\x3a\x16\xa3\x44\x61\x1f\xbd\xc3\x52\xdf\x8e\x4f\x02\x38\xcd\xfe\x4a\x8f\x1c\x7b\x6b\x22\x2d\x77\xe0\xe7\x7a\x1e\xc6\x16\xdc\x2c\xdb\x70\x73\x38\x2d\x56\xd5\xf7\x48\x58\x60\x62\x77\xe9\x7d\x52\xbc\x0f\xca\xf7\x4a\x10\x9a\x04\x90\x18\x6c\xce\xa7\x88\xcd\x33\x54\x8f\xe6\xab\x91\x37\x4b\xa6\x15\xc4\x2e\xf3\x1e\x22\xaf\x40\xec\x3f\x7c\xc2\xd0\xd3\xa4\x44\xee\xc6\x8d\x58\x2f\xaf\x37\xd5\xc8\x9d\x55\x90\x7b\xb2\x1e\xb9\x27\x53\x3a\x52\x5f\x18\x52\x3b\x31\xc8\xdd\xf5\x50\xd3\x95\xe2\x77\x15\xb7\x82\xcc\xa1\x97\xa5\x16\xa4\x5c\xed\x29\x85\xa9\x47\x52\x6c\xf4\x6f\x24\x03\x02\xb1\x40\x4c\x9b\x49\xc1\x82\x82\xdf\xce\xf5\x18\xf8\xf5\xa6\x90\x39\x0f\x50\xd6\x96\x10\xf7\xbd\x3d\xaa\x24\xef\xcf\x41\x6e\x8f\xea\x29\x29\x59\x31\x2f\xd9\x1a\xd6\x05\x63\x68\x35\x88\xb8\xe8\xa5\xc4\xa6\x60\xbd\x8e\x51\xef\xa3\xb9\x7e\x2d\x99\xa1\x79\x8f\x00\xcf\xab\xba\xbb\x89\x51\x29\x34\x4b\xf8\xbb\x9c\x50\xb7\x9d\x13\x62\x0d\x9c\x50\x9d\xff\x89\xa6\x28\x0a\x03\x2e\x43\x45\xfb\x0b\x5c\xc9\x10\xf7\xa7\x44\xfb\x4a\x3c\xec\x5c\xf3\x79\x27\x48\x44\x31\xe9\x5c\xdf\x60\xf4\xfd\xff\xa6\xee\xfe\x25\x3a\xe7\x7a\xcb\x4a\xee\xf2\x9b\x95\xb7\x86\xbd\x20\xdc\x21\x99\x13\x53\x85\xf1\x62\x27\x53\xf8\xaf\xba\xca\x8a\xcf\xf0\x92\xf1\x24\xe2\x92\xf7\xc6\x3c\xce\x3a\xd6\x06\x21\x59\x9f\x6d\xfd\xfa\x95\xf5\xdd\xd7\xf4\xe1\x43\x75\xf4\xac\xf4\x32\x99\x29\x5a\xa7\x18\x68\x8f\x24\x78\x6e\x28\x04\xfa\xb1\x72\xa1\x21\x57\x29\xa0\xea\xb5\x54\x87\x64\x53\x85\xe3\xb4\x62\x30\xa7\xcb\x6a\x65\xe5\x82\xc2\x74\xea\xfc\xec\xda\x4f\x16\xd0\xbd\x83\xf8\x36\x12\xd9\x52\x32\xb4\x9b\xca\xd7\x49\x7b\x27\x8c\x8c\x3d\x22\xfa\xde\x97\x15\x7d\x50\x9c\x93\xe9\xca\x2d\xe5\xd4\x64\xcb\xba\x6c\x20\x84\x1a\xe9\xc7\x0a\xed\x97\x09\x9b\x5b\x93\x6b\x5e\xcb\x3b\x52\xb4\xc6\x7d\xef\xcb\xa2\x10\xf2\x3e\x4b\x1d\xec\x40\x2c\xeb\x8a\x57\x25\x69\xc5\x2a\xaa\xad\xc5\x49\x87\x02\x2c\xc9\xdc\x77\xb1\xcf\x6f\x30\x93\xd0\x90\xe6\x6b\x51\xb9\xc1\x10\x3c\x62\x7a\x01\x5b\x84\xdf\xe5\x2d\x56\x4b\x36\x35\xf7\xb9\xa8\xd8\x10\xbd\xed\x35\x4b\x5c\x82\xe8\xa1\x31\x06\xb4\x3b\xd6\x86\x36\x33\x43\xf3\x1f\x51\xc1\x82\x93\x69\xbb\xb5\x92\xbb\xff\xeb\x97\xe8\xbb\xaf\x47\x0a\xb0\xa5\x23\xa8\x42\x8c\x98\x0c\x6c\x0f\xf5\x8e\x9a\x86\xa3\xe9\x65\xf4\x97\x08\xb9\x34\x84\xdc\x2b\xc8\xb6\xbc\x7f\x7b\xa9\xdb\xae\xdb\x0a\x5c\xa1\xce\xea\x79\xc3\x93\x85\xa7\xea\xb2\x3c\x55\x97\xfa\x54\xfd\x0b\xbb\x54\x72\x06\xf5\x04\xb3\x8a\x0d\xe0\x48\xdf\xa6\x53\x24\x86\x17\xde\x0a\x53\x50\xa1\x9e\xe1\x94\x8e\x26\x1e\xf1\xa8\x6d\xd8\x01\xf5\x8b\xe9\x5f\xc1\x94\x8e\xc6\x9e\x96\xb5\x39\xb4\x05\x7a\xd4\x30\x9c\x51\x4a\xed\xd7\xee\xa2\xb0\x01\x28\xc1\xc5\xf8\xf8\x5b\x60\xb9\x51\xe2\x5d\x97\xea\x5b\x83\xef\x87\x83\xc1\xff\x55\x2a\xa5\x5a\x50\x4c\x67\xe9\x57\x4f\x84\x17\x97\xb2\x44\x3b\x5d\x14\x4b\xa5\xc6\x37\xf6\x8c\x5c\x4e\xd1\x7d\xc0\x7d\x41\xcb\x8b\x7b\x60\xe0\x2d\x28\x5c\xac\xa1\xc1\xef\x34\x0f\xc9\xf4\x2d\x7f\x57\x5f\xf3\xef\x68\x17\xe0\x13\x40\xc7\xa6\x37\x3a\x46\xde\x6b\xbc\xb1\xf0\x7e\xac\x57\x2e\x7b\x4c\xf8\x9d\x2a\xf9\xad\x17\xf6\x2e\x39\xf3\xab\xcc\xfc\x65\x15\xc0\x3a\x0a\xc8\x24\x73\xd3\x4e\xa5\x2e\xbe\xc8\x1b\xdc\x90\x57\x3e\x0c\xc0\xd3\x28\x64\x9f\x61\x52\x48\x73\x12\xdf\x18\x43\x49\x45\x26\xb0\xde\xb0\xb1\x9e\xe8\xb3\xcb\x91\x85\x26\xbe\x1d\xa2\x39\x02\x6a\xd9\xfa\x45\x2e\xee\x79\xfe\x52\xd6\xc9\x19\x99\x4c\xb5\x1e\x99\x51\x0a\x73\x72\xeb\x43\x2e\x30\xfa\x16\x88\xfe\x17\x38\x65\xf9\xfb\xf2\x72\x0f\x44\xff\x08\x3e\x16\x05\xfa\xc6\x0d\x44\xff\x18\x76\x59\x4e\xce\x56\xd6\xc7\x40\x8c\x9e\xad\x37\x2a\x87\xc2\xf3\xa1\xf8\x53\x54\x6a\xb3\x4b\xdc\xf8\xbc\x58\xe6\xc5\x72\x0a\x3f\xbd\x73\xfb\xc1\x00\x41\xb4\xfa\x99\xd3\x36\x9e\x2e\x17\xa4\xcb\x8b\x92\x15\x03\x99\x2d\x4d\x55\xcc\x7d\xc7\x26\x30\xfb\x41\xbc\x30\x64\x32\x1e\xad\xb3\x34\xd8\xaa\x4a\xd9\x2f\x93\x28\x62\x93\x94\x77\x58\x14\x19\x05\xb9\x45\xbf\xdb\x6b\x2c\x07\x96\x9a\x6b\xf3\xca\xe5\xc6\xf9\x04\x43\x1f\xe6\x64\xd7\x87\x04\x42\xc5\x3c\x49\x83\x7b\x67\x5a\x2b\x77\x39\xb4\x28\xcc\xa7\x4b\x16\x59\xb3\x69\x69\x91\x15\x27\x32\xd7\xd4\x9b\x1e\x6f\x74\x43\x44\x32\xa9\xb6\xec\xd0\x1a\xbd\x4b\x39\x8e\xde\x24\x8a\xcc\xee\xdc\x53\xc4\xbd\x4b\x53\x2e\x98\x1f\x26\xff\x92\x9a\x5c\x20\x16\x8c\x11\xfd\xc9\xff\xa4\x6a\x7c\x41\xe1\x68\x6a\x4c\x76\x8f\xa7\x26\xec\xe4\x6b\x7c\x18\x0e\x16\x70\x86\x4f\xbf\x2f\xe0\x0a\x1f\xb6\x17\xf0\x72\xda\xea\x0c\x5c\x11\x9a\x07\x7f\x38\x18\x85\x5c\x47\x20\x57\xf2\x8b\x59\xd6\x77\x92\x64\x1a\xc5\x79\x4e\x0c\x89\x23\x20\x74\x24\x04\x0e\x07\xd7\x31\x17\x5a\x19\x85\xd4\x31\x81\x86\x05\xe6\x2e\x7e\x1e\x3b\x1e\x08\x27\x01\xe9\x84\xc0\x9d\x00\x32\xc7\x05\xe6\xa4\x4a\xc2\x3e\x9f\xae\xf5\x0f\xeb\x04\xe4\xe5\x14\x3d\x46\xbe\x49\xcc\x2b\x84\x6e\xee\xa7\x30\x27\x5f\x53\x0c\x5b\xa8\x83\x2c\xee\x4d\xdb\x0c\xf2\x4c\x4e\xb5\x5a\x72\xcc\xe1\xf6\xf6\x80\xd2\x95\xf4\x59\xb5\x28\x01\xdb\xf5\xc4\x64\xb5\xd0\x10\x4f\x6a\x3e\x8f\x83\x7a\x3a\xb2\xba\x71\xdf\x26\x66\x04\x69\xa3\x07\x13\x8c\x99\xce\x9d\x29\x39\x9f\xc2\x70\x08\x18\x73\x57\x02\xc9\x9c\x1d\x45\x13\xf7\xa6\x26\x62\x70\x11\x4d\xf8\x69\x4f\xfb\xb1\x8d\x32\x7b\x88\x3a\xe6\xa7\x76\xd6\x1b\xd2\x3c\xb0\x30\x64\x4e\x19\x69\x38\xa6\x10\x3b\x24\xae\x76\xa5\xd5\x0c\x45\x68\x62\xd3\xd7\x53\xc7\x71\xe2\xd1\xc0\x8e\xb1\x4f\x7c\x32\x7d\x66\x14\x96\x86\x16\x57\x55\x0b\x72\x79\xd8\x19\x48\x8a\xb6\x9f\xbb\x24\xdf\xa3\x8f\xad\x5c\x18\x46\x1d\xf9\xe3\xe9\x48\xd8\x33\xf2\x71\xaa\x44\x18\x17\xd3\xe0\xc1\x8c\x7c\x4a\x40\xe8\x53\xe9\xeb\x77\x46\xef\xb6\x8b\xf0\xbc\xb5\x80\xd3\xe9\x9d\x96\xa8\xbf\x7e\x19\x9f\x39\xe3\xc9\xb2\x14\xbd\x75\x41\xe1\xdd\x52\x17\x12\x93\x04\x19\x4b\x81\x0b\x72\xe4\xa9\x4d\x39\xf2\xd4\x21\x18\x59\x78\x0d\x3e\x4e\x62\x79\xa9\x84\x17\xc8\xda\xef\x46\x8a\xa8\xc0\x71\x11\xa8\x56\xd0\xb5\xc1\x92\x1f\xc4\xfd\xee\xc3\x87\x43\xb4\x52\xcf\xd0\xa0\x83\xd3\x91\xb0\x2d\x6b\xa1\x99\x48\x1c\xf0\x15\x58\x1d\xae\xb0\x24\x2a\x98\xf0\x95\x00\xab\x33\x4e\xb2\x94\x27\xe8\x12\x83\x7a\x22\x2c\xb8\x05\xab\x63\x64\x63\x88\x9b\x83\xac\xb1\x5b\xec\xb4\x2d\xc0\x9a\x65\x15\xf7\xb3\x2e\x5a\x7b\x9d\x13\x33\x36\x1c\x1d\xa8\x1f\x02\xc3\xaf\x63\xa0\x69\xf6\xeb\xd7\x26\x06\xcb\x75\xcb\xf6\xe6\xa1\xe3\x72\x39\xe3\x3c\xb6\x16\x84\xe6\x7c\xf5\x39\xc1\xdc\x0b\x8a\x3e\x9f\x4e\xa1\x35\xff\x5a\x08\xe8\x8c\x5e\x0e\xb6\x51\x9d\xe5\x33\xc9\x3b\x2e\xf3\xae\xad\x0d\xc2\xfa\x4c\xfd\xe3\x6e\xc4\xb4\x51\x92\x54\x55\x03\x91\xc4\xd2\xda\x48\x36\x48\xb8\x41\xbc\x0d\x13\x0d\xce\xf7\xc1\x2a\xd7\x12\x52\xf4\x3a\xcf\x13\x23\x2b\x02\xbc\x3b\x2d\x71\xf0\x99\x02\xa5\x0f\x18\xef\x9c\xd3\x8a\xb8\xf1\x69\x2d\x59\x5a\x62\xdb\x4e\xf3\x3b\xfd\x77\xd3\x3c\x57\x98\xe9\xe4\x70\xda\xea\x39\xba\x8f\x62\x02\x06\xcd\x52\x3f\x3f\x4e\x41\xc2\x29\x6d\xbb\x3e\xba\xca\x52\x19\x06\xf3\xe2\xda\xa6\xae\xcd\xad\xd8\x87\x71\x7e\x5d\x61\x0f\x71\x64\xc7\x1e\x1c\x9a\x88\xda\xde\xcd\xe8\x4f\xeb\x28\x53\x52\xc3\x07\x94\x1d\x8e\x33\x25\x26\x7c\x55\x4c\x95\x75\x7c\x99\x59\x60\xbd\x11\xa1\x05\xd6\x11\x93\xd6\x77\xfb\xcf\x7b\xd4\x42\x57\x0c\x63\x1a\x5b\xdb\x20\x1c\x2f\x0b\x63\x73\x7b\x5a\x6e\x4c\x26\x71\x5f\xae\xa6\xb4\x62\x12\xf1\xa9\xbe\x7c\x27\x88\x1f\x06\x0b\xb8\x9d\x9a\x20\x9c\xaf\x34\x3f\xe1\xaa\xfe\xde\xea\xe7\x89\x45\xe1\x4d\xfb\x66\xfd\xec\xda\x4f\xaa\xd9\xad\x31\x10\xc6\xda\xea\x8f\xeb\xd5\x3f\x98\x3b\x49\x29\x92\xf8\xc2\xa2\x6b\xf2\x61\xaf\xc4\x21\x31\x29\xd5\xe2\x7e\x77\xf4\x36\xb1\x53\x4e\xb5\x07\x9e\xc2\x8e\xbc\x48\x42\xd8\x6e\xd2\x90\xa7\x4d\xaa\x64\x4c\x22\x96\x57\xc4\xe2\xf3\x92\x78\xca\x85\xec\xa4\x52\x84\x7a\x64\x53\x7d\x73\xfb\xde\xf0\xb3\x73\x0e\x9e\xa0\x14\x5e\x4c\xdb\x7c\x57\xeb\x80\x26\xc3\x31\x9f\x84\xde\x75\x15\xb8\x3e\x14\xda\xad\x34\x73\xaf\xb8\x27\xab\xd6\x32\x23\xeb\x75\xec\x5b\xb6\x75\x94\xeb\xef\x96\xa1\xe0\x32\xc9\x44\x93\x26\x34\x9b\xf4\xb4\x49\xbc\xb9\xab\x28\x20\x5a\x9d\xcf\x39\x79\xa3\x8e\xc3\x00\xd6\x18\xc5\xb2\xf8\x22\xe2\x3d\xa3\xf6\x3e\x35\xdf\x7d\x67\xee\xfd\x15\xa0\xb9\x51\x26\x2c\xbd\xd0\x33\x72\x80\xfd\xa9\x05\xa2\xc8\xe4\x55\xf0\x68\x18\x10\x99\x63\x53\xd1\x67\xd7\xd5\xd8\xa3\xd6\x00\x2d\x8c\xf2\x54\x0a\xda\x71\x02\xab\xed\xdc\x59\x8d\x50\x0a\x67\x1e\xd9\xd4\x5c\xe7\x34\xe4\xb3\xfa\x54\x73\xae\xb1\x72\x41\xa4\x24\xd5\x7b\xac\x4b\xef\xce\x85\x51\x3d\x95\x4b\xb3\x22\x24\x25\xd1\xea\x17\x4a\x6d\x8c\xbd\xba\x8f\x4a\x12\x91\xfc\xef\xee\xe4\xf0\xdf\xbc\x93\xc3\xbf\xbf\x93\x3f\xee\xb7\x93\x3f\xd6\xee\xe4\xdf\xdf\xbb\xe1\xbf\xbc\x77\xea\x84\xb6\x40\x93\xde\x3e\x12\xb7\xa3\x27\xed\xc0\xd9\xa6\x93\x51\xe8\xc6\xb2\xec\x19\x99\x27\xf0\x3b\x48\x64\x7b\x16\x06\x49\xc9\x91\xe1\xb8\xae\xd5\x3f\x57\xa8\xf5\x56\x4f\x3b\xea\x9f\xdb\x82\x72\x22\xab\x11\x2f\x28\xfc\x98\x36\x85\xb4\x37\xee\x48\xe5\x85\x7f\x83\xa1\xe1\xb8\xe3\x5e\xf4\x02\xe6\x73\x7f\xd5\xf0\x70\x13\x2d\x9f\x5b\x0c\x35\x25\xbf\x91\xeb\xac\x34\x97\xcb\x1b\x4d\x34\x75\x95\xe5\x6b\xd8\xe7\xf1\x72\x2c\xec\xe0\x6f\x0e\xf9\xa4\x6a\x92\x5b\xce\xbb\xf1\x9e\x40\x94\x8c\xc8\xe7\x69\x6b\x42\xd9\x36\x63\x62\x1d\x05\xc9\xd1\x51\x90\x30\x9a\xa8\x8b\xd6\x9d\xbb\x84\xc8\x3b\x2c\xe3\x73\x13\x3f\x34\x72\x97\x7d\x77\x95\x4f\x5b\x6f\xe5\xfe\xf7\x6c\xd8\x2b\x16\xeb\xc2\x58\xac\x0b\x63\xb1\x7e\xec\x23\x53\x50\x58\xa2\xa3\xcb\x42\xcd\x12\x5d\xc9\x00\xda\x62\x79\xd9\xef\xe3\xfe\x16\xcb\xa2\xdd\x62\xf9\xc7\x14\xdd\x46\x78\xbe\x1f\xef\xa7\xed\xc7\xab\x62\x5d\xc9\x06\xfa\x73\xe5\x97\x3e\xa3\x6e\x41\xdb\x26\x7e\x9d\xde\xc7\xf7\x6c\x25\xc9\xcb\xca\x22\x9a\x85\x93\x7d\x77\xf4\xe7\x8c\xbc\x9d\xe6\x5c\xe9\x87\x8a\x56\x66\x27\x0f\x92\xaa\x2f\x99\xec\x0e\x3a\x01\x7e\x15\x98\xe0\xa4\x40\x30\xef\xa7\xe8\xee\x81\x6a\xa4\xe6\x7e\x3e\x26\x65\xbc\xd5\xca\xf5\x97\x39\xf7\xcb\x42\xb8\x5e\xc7\x7a\x1e\xeb\xd2\x4f\xae\x75\x56\xda\xea\x13\xff\xed\xcd\x98\x88\x91\xaf\x59\xb6\xcd\x55\x2c\xd9\xb7\x69\x7b\x2c\xc1\x06\xef\xbd\xea\x70\x06\x65\x70\x23\xcf\x87\x97\x1e\xcc\xc8\x57\x3d\xf7\x7a\x06\x1f\xe3\xc5\x57\x97\xff\x99\xaf\x46\x10\x77\x1d\x6b\x2c\x7b\x8f\x2d\x10\xdd\x15\xf3\x82\xd5\x89\xed\x92\xb8\x0b\xc6\xfb\x65\x64\x75\x96\x2e\x61\x2d\x5a\x33\x0c\xbd\x9e\x36\x9b\x56\x55\x18\xb2\x62\x57\x3e\x98\xe4\x82\x1d\x4d\xb3\x71\xc3\x71\x73\xca\xcd\xca\x0d\xbf\xd3\x8a\x75\x8e\x56\xcf\xbe\xc8\x2a\xba\xce\x21\xa2\x7a\x58\x26\xa8\x5a\x14\x2c\x10\xb6\x59\xc8\x82\xc6\x36\x6d\x61\xd5\xbe\xa0\x17\x70\xee\xa3\x40\x57\xd3\x7a\x2d\x88\x39\x4e\xb2\x6b\x58\x7b\xde\x75\xd6\xaa\x55\xcd\x2d\x35\xe2\xd1\x13\xb7\xc2\xad\x7c\x16\x9a\x1e\xee\x94\x30\x09\x59\xf7\x3e\x87\x54\xe1\xa7\x8e\xb5\x11\x77\x4d\x6f\xbc\x5b\x73\xe3\x40\x96\x00\xbd\xba\xb9\x65\x5b\x5f\x30\x73\x64\xa3\x65\xcf\x38\xea\x6d\x76\x56\x6f\xf7\x4f\x18\x91\xdd\x95\x99\xc7\xcb\x8c\xc3\x52\x5b\x03\x14\x5a\x4f\xbc\x74\x41\x86\xea\xd3\x82\x2a\x30\x5c\xb6\x67\x0b\xf0\xba\x46\x87\x92\x74\xef\x48\x51\xc2\xfa\x8c\xe7\x91\xe6\xbc\x4a\x94\xf0\x26\x39\x5c\xdb\x0f\x69\xfe\x22\x89\xb2\xb1\x4e\xa0\x60\x4c\xd9\x2b\x46\x03\x1d\x6b\x43\x56\x81\x77\x15\x6d\x88\x12\xc5\xe0\xad\xa9\x98\x2a\xa1\xfe\x0c\x95\xac\xfa\xc2\x29\x5b\x35\x4b\xe9\x2c\xc1\x50\xb1\xf5\x39\x4b\xb4\x72\x90\xef\x3b\xf2\xff\x99\xd1\x56\x06\x96\xa3\x0a\xed\xbd\xe2\x35\x1f\x90\xbb\x57\xd7\xf8\x26\xfd\x27\x16\x37\x07\xb8\xd5\x8b\xb4\xbb\xce\x71\x92\x43\xe3\x82\x42\xd8\xbd\x43\x5b\x52\x11\x31\x2b\x07\x2e\x20\x49\x17\xde\xf9\x60\xa4\x47\x50\x82\x49\x2f\xba\xe8\x6d\xa3\xb9\xe3\x13\x13\x39\x66\xdf\x83\x1b\x8f\xc2\x8d\x47\xbc\x2e\x85\x98\x42\xd1\xec\x95\x49\xef\x51\xb6\xdc\x5a\x6a\x79\xbe\xd4\x52\x56\x5a\xbe\x46\x73\xf0\xc6\xcf\xed\x2d\x35\x12\x0d\x8b\xa2\x37\xca\x34\x1e\x9a\xc6\x2b\x3b\xa5\x8e\xed\xff\xf3\x7f\x5b\x2b\x8e\x3b\x4b\x7b\x51\x47\x73\x06\x77\x74\xf4\x65\x79\x6f\xc9\x1a\xe1\xc6\x23\xac\xdb\x2e\x3c\x78\x2c\xe2\x8a\xeb\x5c\x12\x1d\xbe\xd3\xbb\x9c\x26\x42\x01\x8f\xfe\x9b\x24\xf1\x2f\x35\xae\x1d\xac\xd1\xa5\x8f\xc2\xbe\xe4\xa9\x24\xb1\x13\xd3\x91\xe5\x33\xc9\x7a\xd6\x46\x6c\xc7\xf0\xe8\xbf\xff\x99\xfe\x46\xae\xd8\x94\xe9\x0b\x0d\xfb\x97\x2a\xb4\x15\x13\xfb\xcf\x47\x97\x72\x1c\x15\x4d\x85\x23\xd0\xe4\x08\x43\x76\x07\x0a\xb9\x7b\x02\x74\x57\x17\x82\x8d\xc7\xe7\xdc\x0f\x31\x58\x46\x1e\x31\x0a\xdc\x6e\x9b\xd7\x70\xee\x2e\x2c\xfe\x19\xff\xfa\xa7\xf8\xf5\xcf\x58\x7b\x0d\xa7\x5d\xed\x1b\xca\x6f\x24\x13\x9c\x59\x14\xa2\xee\xda\xbc\x53\x98\xd5\x7f\x0b\x86\x8f\xe1\xab\x20\x6e\x57\x67\x31\xc5\xeb\xfd\xec\x7f\x06\x39\x8a\xf5\xe7\x37\x2e\xcf\x6f\xda\x35\x07\x38\xcb\x0f\xb0\xc4\x03\xcc\xef\x8d\x1d\xe1\xa3\x47\x98\x5a\xea\x7f\x03\x9a\xfc\x1f\x19\x77\xd3\x10\xff\xdd\x08\xf3\x3f\xb0\xe0\x05\x89\x5e\x9a\xcc\xdf\x46\x9d\x7e\xb7\xd1\x23\x46\xc7\x7f\xe5\x7d\xf6\x18\x30\x5f\x5a\x17\x3c\xf5\x67\x00\xe8\x14\xf9\x11\x42\xf5\x6b\x0f\xb3\xa8\xb1\x57\x18\xc2\xaa\x3b\x3a\x27\xd6\x47\x3e\xcb\x93\x20\x28\x74\xf6\x1a\x1d\x7d\x30\x42\xad\xf5\xda\x0f\x65\x59\xf6\x96\x13\x13\x30\xaf\x1a\x90\xac\xe5\x66\x37\x17\xb0\xe6\x24\xec\x42\xd6\x77\x0f\x20\xeb\xb3\x53\xc8\xfa\xa9\x9a\xb7\xe8\x82\x07\xac\x82\x5c\x8b\x38\x38\x71\xd7\xe8\x21\x0b\x94\x7a\x3c\xc5\xf4\x9c\x27\x14\xa6\x24\xea\x82\xf5\x32\xcf\xaf\x9d\x57\x9d\x15\x55\x8f\x74\xd5\xe3\xa5\xa5\x2d\x48\xc7\x9c\x7c\x9b\x02\x87\x44\x07\x5d\xca\xba\x28\x25\xaa\x31\x5e\x29\xa2\xa7\xd1\xde\xb4\xeb\x70\x01\xdd\xae\x93\x09\x18\x37\x22\x97\x58\x90\x40\xa0\x9a\xc3\x44\x94\xb8\xec\xde\xd3\x8c\x79\xd2\x5a\xd1\x63\x28\x46\xee\x08\xde\x99\x27\x59\x27\xcd\xcc\xc3\x8c\xc5\xb2\x23\x93\x8e\x4e\x8f\xbe\xc4\x92\x8f\x2c\x0a\x6c\xdb\x5e\x6f\x2a\x7a\xc2\xc8\x01\x27\x33\x72\xa9\xe7\x5a\xb5\xf0\x7b\x99\xc4\x41\x28\xc6\x9a\xd6\xb8\x3f\xec\x03\x4e\x8e\x13\x0a\xde\x13\xdb\x7a\xad\xbf\x96\xef\x3b\x26\x90\x59\xc3\x1c\x37\xe9\x25\x8c\xb9\x61\xca\xa3\xc0\x68\x9b\x4a\xc3\x7f\x73\xac\x36\xd0\x1c\xfc\xdc\x37\x31\xf4\xd0\x66\xa0\xf5\x2b\xe8\x60\xb0\x41\xac\x87\x26\xde\x97\x76\x8e\xd6\x82\xf1\x5c\xa3\xf4\xcb\xc7\x16\x85\x9b\x35\xe3\xfc\xdf\xe9\x71\xbf\x1a\x62\xca\x64\x70\x58\xa5\x27\x17\x5d\x64\x42\x52\x0b\x44\x9f\x9d\xd6\x45\x4f\x5d\x8e\x5c\x11\xd6\x70\x0f\x56\xc4\x50\xd3\x85\xc9\xb5\xaf\x7b\xc1\x08\x55\xa8\x22\x71\x7d\xf8\x8b\xee\xe2\xcb\x21\xe4\x65\x05\xba\x4e\x8c\xc6\x93\x52\x38\xf5\x88\xa0\x8d\x91\xd6\x97\xe6\xb9\x5e\x0f\xb0\x4e\xcc\x5b\xf1\xca\x37\x60\xbf\x8b\x4e\x29\x95\x41\xe9\x89\x5b\x4b\x44\xe4\xdf\xd9\xff\x2b\x1e\x71\xad\xf0\x56\xab\x2a\x56\xd4\xb0\xa5\x5e\xe7\x93\xa7\x36\xe8\x9a\x52\x38\xf4\x48\x3c\xc2\xbb\xe9\x49\x17\x04\x3c\x18\x52\x6a\xef\xc8\x42\x2d\x2a\x17\x14\xae\xbb\x0d\xc1\xfa\xcc\x1a\xca\x9a\xea\x87\x57\xe2\x09\x62\x48\x0b\x13\x51\xb4\xcd\xa0\x8e\xcd\x17\xda\xc2\x74\xad\xe9\xa8\x7b\xb2\x30\x26\xa3\x78\xe1\x49\x29\xba\xd8\x8f\xbb\xab\x3e\xcb\xe5\x14\x1b\x3a\x3a\x57\x5b\xae\x80\xec\xa6\x9b\x47\x0a\x50\x2f\x28\x9a\xf1\x2e\x30\x68\x8c\x71\xe4\xcd\xa1\x2a\x37\x0d\x5a\xd5\xb2\xc8\x56\x2d\xcb\x4e\xb7\x9a\x43\xe4\x68\x8d\x94\x81\xb6\x6a\x32\x0f\x4b\x7a\xe2\xc1\x01\xaf\xeb\x32\x44\x71\x39\x50\x09\xd2\x98\xf9\xe4\x1d\x23\xb7\x1e\x6a\xc3\x96\x4c\x78\x5c\xe6\x5f\xf0\x0e\xfe\xdb\x9b\x84\x51\x94\xcc\xcc\x0f\x33\x52\x83\x06\x10\x4f\xca\x64\xb2\xe4\x88\xa5\x2f\x96\x63\xc3\x82\x2f\x5a\x3e\xf7\x1d\xef\x16\x16\x14\x8e\x57\x55\x48\x61\x40\x74\x72\x8a\x8a\xb2\xbc\xc5\xcc\xaf\x40\x5c\xe6\x1e\xf5\x48\x01\xdf\x40\x2d\xde\xaa\xf2\xfa\x5e\x5d\x34\xc6\xa7\xc0\x5e\xe3\xbe\x77\x05\x0a\x86\x8a\x7b\x81\xd7\xff\x9b\xe9\xe0\x07\xbc\xfa\xc7\x0b\xdd\xbe\xeb\x2f\x5a\x29\xe2\x59\xd7\x18\x56\x5d\x69\xf2\xe3\x5a\x14\x5e\xde\x4b\x85\x54\xe1\x43\x45\x32\x6b\xf2\xf0\x56\xd2\xe1\x26\xca\x88\x58\x77\x29\xfa\xc2\x8c\x5c\x75\x9b\x78\xd3\xa5\x9b\xba\xde\x70\x70\xb7\x43\x97\x28\x64\xbd\xf3\x66\x7e\x52\xb4\x86\x5f\xf8\x50\x44\xe5\x37\xd1\x5f\xbe\xea\x7b\x78\x7a\x07\x53\x58\x7a\xfb\x41\x2d\xe0\x42\x61\xb8\x7a\x8a\x4c\xf5\x7f\x9a\x5c\x7c\xe0\xe4\xac\xfb\x3f\x45\x2b\x56\x3a\x5f\x26\x14\xb2\xdc\xc4\x97\x5d\xb0\xde\xbd\xb2\x4c\x34\x33\xbf\x78\xa7\xa9\x7a\x87\x49\x2c\x3a\xc7\xd2\x03\x5a\x14\x2b\xa6\x60\xa9\x90\x9d\x96\x85\x5a\x05\xe9\x2f\x37\xae\x94\x6b\x5d\xa5\xdf\x71\xe7\xe6\xbb\xec\xa4\x2c\xcb\x59\x6d\x5d\x70\x5c\x1d\x90\xe4\xf8\x5a\xe1\x25\xb3\x33\x45\x69\xae\x60\xb6\x60\xd9\xd8\xe5\x3c\x81\x77\x9e\xb9\x1d\xa1\x20\x75\xca\x1b\x10\x8a\x08\x72\x4d\x04\x5f\x77\x41\xc2\x83\x41\x41\x04\x17\x14\xf6\x0c\x7b\xb7\x69\x51\xd8\xd7\xcf\x5e\xe2\x2b\x10\xfa\xa8\x7f\x4d\xd4\x3e\xc1\xae\xa9\x66\xec\x58\xe0\x54\xff\x8e\xd9\xd4\xa2\xf0\xae\xeb\xfc\xbc\xb1\xcb\xbc\x06\xe0\x26\xb6\xd1\x79\x5b\x0b\xf8\xa4\x4b\xf5\x5b\x6b\x01\x87\x79\xed\x22\x3e\x30\x96\x1c\xe5\xbf\x16\x70\x52\xd4\x28\x92\x22\x61\x8d\xfc\xd7\x02\x6e\x8b\x1a\x26\x5d\x0b\x96\xeb\xe7\x05\xbc\xea\xb6\xc7\x21\x6b\x04\xfd\x6e\x1d\xec\xdf\x75\x6b\x20\xff\xa9\x9b\x13\x49\xc3\x0e\x18\x13\xc5\x65\xcb\xc4\x93\x6e\x2d\x9d\xe7\x6d\xb7\x96\x6d\xe2\x53\xb7\x0e\xef\x87\xdd\xc5\x42\x5f\x43\x8d\xac\x4e\xe9\xad\xba\xa0\xf0\xf6\x4e\x6e\x7b\x29\x2a\xc3\xc6\x8c\xbc\x32\x08\x78\xd5\xb9\xb8\x12\x0d\xe1\x96\x11\xd1\xbf\xc1\x40\x34\xc6\x5b\xa6\xe6\x3b\xa3\x01\xe3\x0d\x12\xfa\x77\x5d\x38\xe9\xc2\x6d\x17\x0e\xbb\xa0\x56\x3c\x0f\xbc\x37\x11\xc9\x98\xcb\x4b\x9e\xa5\xfd\x30\x79\xe4\x27\x5e\xaa\x37\x3f\x8c\x2f\xf4\xc3\x98\xc5\xec\x82\x8b\x47\x7a\x6b\x76\x79\x34\xb1\x16\xdf\x29\x1c\xac\xc7\xe1\x4b\x96\xf7\x46\x96\x60\xbe\x8f\x4e\x6d\xd6\x36\xba\x93\xe5\xbe\x2b\x26\x46\x8f\x58\xbd\xa5\x85\x0f\x1e\x89\xfb\xde\x69\x1d\x6f\x1b\xc3\xa7\xce\xa4\x22\x56\x1c\x78\x55\x9b\xdf\x0f\x5d\x27\x14\xc4\x12\x18\x7e\xe4\x4b\xb7\x3d\xf1\xfa\x67\x0f\x2c\x5c\x4e\xd5\x07\x46\x76\x82\x0f\x5d\x62\xa5\x72\x1e\xf1\xf4\x92\x73\x59\x58\x57\x45\x09\xf3\xd1\xb2\x4a\x10\x0f\x63\x3a\x17\x06\x71\x5c\x88\x44\x98\xa2\x38\x23\xd6\x1b\x16\x46\xdc\x57\x74\x58\xb5\xe9\xbc\x3c\x3a\xea\x04\x22\x19\xeb\xf4\x45\xd4\xf8\x37\xea\x18\xa3\x87\x31\xf9\xe9\xbd\xb2\xaf\xc0\x3b\xb0\xcf\x19\x78\x87\x76\x23\x63\xd9\x1d\x29\x32\xa2\x89\x2d\x5b\xd8\xea\xc7\x36\x30\x7b\x4e\xbe\x46\x60\xfd\x97\x05\x24\xd6\x59\xd3\xd8\x13\xd0\xef\x46\x96\xe2\x27\x8e\xd1\xe1\xef\x7d\xa4\xd8\x8a\x0c\x76\x15\x69\x98\x8f\xca\x90\x8b\x76\x19\x87\x31\xee\xbb\x9e\xe2\x2f\xfb\x2c\xc3\xf8\xf4\xe0\x6d\xdb\x5d\x49\x7e\x08\x0a\xde\x33\x7b\x3f\x02\xdf\x6d\x18\x99\xe2\x43\x0e\xc9\x9f\xef\xf5\xd2\x23\x07\xb0\x53\x01\x19\x6b\xb1\x58\xd0\xe7\x2c\x71\x7e\x7e\x60\x61\x6c\xff\x0c\xe3\x50\xda\x3f\x04\x39\x0c\x29\x19\xa8\x8f\xc4\xfd\xd7\xd1\x78\x94\xf7\xdb\x31\xe6\x53\x41\x22\x08\xf2\xe8\x9d\x30\xee\x48\x8a\x7f\xc4\x08\x43\x3c\x59\x8e\xc3\x47\x13\xf2\x84\xda\x31\x11\x7f\xf2\xef\x20\xff\xe4\xdf\xa9\xad\x1e\x1d\xf5\xb8\x20\xd8\x25\xb0\x84\xda\xf8\xe4\xb0\x64\x41\x14\x1b\x44\x9f\xff\xbf\x01\x00\x00\xff\xff\x01\x30\xcf\xe3\xfa\xaf\x01\x00"), }, "/templates": &vfsgen۰DirInfo{ name: "templates", @@ -163,9 +161,9 @@ var Assets = func() http.FileSystem { "/templates/default.tmpl": &vfsgen۰CompressedFileInfo{ name: "default.tmpl", modTime: time.Date(1970, 1, 1, 0, 0, 1, 0, time.UTC), - uncompressedSize: 5951, + uncompressedSize: 8101, - compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\xec\x58\x4f\x6f\xbb\x46\x10\xbd\xf3\x29\x56\xce\x25\x3e\x98\xf4\x1c\x29\xaa\xa2\xaa\xed\x25\xaa\x2a\x47\xee\xa5\xaa\xd0\x1a\xc6\x64\xe3\xfd\x43\x76\x07\x27\x16\xe6\xbb\x57\x0b\xc4\x06\x2f\x38\x8b\xe3\xdf\xe9\xe7\x5b\xd8\xcc\xbc\x99\x7d\x6f\x98\x19\x5c\x14\x24\x81\x15\x93\x40\x26\x51\x44\x39\x68\x14\x54\xd2\x14\xf4\x84\x94\xe5\x63\xeb\xb9\x28\x08\xc8\x84\x94\x65\x30\xe8\xb2\x98\x3f\x59\xaf\xa2\x20\xe1\xef\x1f\x08\x5a\x52\xbe\x98\x3f\x91\xb2\xbc\xbb\xb9\xab\xec\xcc\xaf\x1a\x62\x60\x1b\xd0\x0f\xd6\x68\xde\x3c\x90\x1d\xc9\x35\x7f\xcb\x41\x6f\x6b\xf7\x26\x50\x37\x92\xc9\x97\xaf\x10\xa3\x8d\xf0\xaf\xf5\x7e\x46\x8a\xb9\x21\x3b\x82\x6a\x91\x65\xa0\x6b\x57\xb6\x22\xf0\xb6\xff\xe7\x64\xc5\x34\x93\xa9\xf5\xb9\xb7\x3e\xd5\x85\x4c\xf8\x47\x75\x4a\x76\x84\x83\x6c\x47\xfc\x8f\x58\xa3\x3f\xb5\xca\xb3\x27\xba\x04\x6e\xc2\x67\xa5\x11\x92\xbf\x29\xd3\x26\xfc\x87\xf2\x1c\x6c\xc0\x57\xc5\x24\x99\x10\x8b\x4a\xea\x90\x29\x92\x5b\x8b\x15\xfe\xa6\x84\x50\xb2\x76\x9e\x36\x67\x2d\xbc\x29\x29\xcb\xdb\xa2\x20\xef\x0c\x5f\xba\xc6\xe1\x1c\x84\xda\x40\x37\xfa\x5f\x54\x80\x69\x18\xed\x8b\xbe\x4f\x7c\xba\xff\x6b\x40\xa6\x04\x4c\xac\x59\x86\x4c\xc9\xc9\x09\x8e\x11\x3e\xb0\x96\x34\xe2\xcc\x60\x63\xaa\xa9\x4c\x81\x84\xa4\x2c\xeb\xbc\xee\x83\xc3\xa1\xcb\x93\x65\x65\x56\x11\x69\xd3\xb7\x4f\x0f\x64\x7f\x81\x26\xb1\x3a\xf8\xa3\x94\x0a\xa9\xcd\xa9\x03\xd9\x3a\x3e\x0f\xf7\x59\xe5\x3a\x86\xfb\x5a\x4c\x90\xa0\x29\x2a\x5d\x57\x62\xd0\x43\xd4\x49\x0a\x22\x41\xf5\x3a\x51\xef\xd2\xe1\x22\xf0\x25\xc3\x33\xeb\x60\x3c\x1d\xbe\xc8\x5e\x84\x04\xfd\x8c\x18\x4e\xe3\x75\x98\xc0\x8a\xe6\x1c\x43\x64\xc8\xa1\xa1\x02\x41\x64\x9c\x62\xf7\xe5\x0c\x87\x6a\xb0\x8b\x93\x1b\xdb\x1e\x44\x1f\x54\xb7\x09\x79\xe2\xad\x28\xe7\x4b\x1a\xaf\x1d\xbc\xde\xf4\x2d\x28\xd9\x91\xaf\x0c\x39\x93\x6b\xef\x0c\xe2\x26\x03\x96\x4c\xfc\x1c\x32\x0d\xb6\xd6\x3c\xad\x5b\x09\x9d\x64\xac\xea\xc1\x9e\x29\xb3\x58\x49\x10\xea\x95\x4d\xfc\xed\x73\xcd\x7d\x33\xf6\xbf\xdc\x4a\x29\xac\x27\x4e\xab\x06\xdb\xe6\x99\xbd\x5a\x92\xe3\x76\xef\xe2\x36\xb4\x71\xe5\xe8\x22\xc6\x9c\x81\xc4\xf3\x0b\x72\x08\xf1\x30\x15\xcf\xd3\xcc\xc5\x65\xd2\x20\x95\x31\x98\x1e\x5c\xa7\x83\x87\xc3\xac\xaa\xcc\xa4\x20\x19\xec\x81\x05\x18\x43\xd3\xf3\xde\x6f\x07\xcc\x55\xa8\x19\x78\x03\x0d\xad\x77\xc2\x05\x47\xf3\xb5\x33\xc0\xa7\xe4\x17\x32\xb3\x8d\xb3\x3a\x24\xf5\x61\xd5\x3a\x4f\x33\xd2\xdd\x02\xaa\x20\xb3\xd6\x8d\x7a\xe2\xcd\xc1\x28\xbe\x81\xe4\x28\xe2\xe7\xb1\x7f\xcc\x4f\x0f\x27\xea\xcc\x87\x52\x53\xf5\xf1\xf1\xd5\xd4\x51\xfd\x1d\xe2\x17\x8a\x63\x35\x0f\xae\xfa\x9d\xd0\xaf\xbd\x28\x2f\x34\x77\xf0\x7a\xf5\x19\x50\xfd\x48\x1f\x54\x91\x1d\x96\x83\x9d\xd4\x35\xcf\xa8\xc6\xed\x08\x7b\xa4\xa9\xaf\x35\x4d\x41\x62\x74\x3c\xe2\xba\xf5\xb5\x61\x31\x2a\xad\x32\x73\x28\x5b\xa4\x08\x51\xb7\xd0\xae\xb5\x34\xae\x17\xb8\xac\x82\x44\x86\xdb\x28\x61\x26\xe3\x74\x1b\x0d\x6c\x53\x5f\x37\x6e\x17\x59\x28\xc9\x50\x59\x42\x22\x54\x8a\x8f\x1c\x89\x9d\xd9\x95\x9b\x17\xb5\x01\x7d\x81\xfd\xd1\x81\xfa\xf1\xf5\x74\x99\x72\xf2\xaf\xa6\xcb\x15\x93\xbb\xd2\x9f\x62\xf2\xb0\xd3\x8d\x99\x29\xed\x6d\x4e\xb6\x5e\xf6\xc3\x67\xfa\xf8\x6f\x84\x16\xce\x55\xde\x31\xf2\xb6\x59\x44\xe0\x90\x6a\x2a\xfa\xa8\xfc\x69\x49\x49\x98\x89\x95\x4e\x2e\xd0\x88\x8e\x91\xae\xec\xda\x35\x61\x09\x1f\xd7\x57\xf7\xdb\x3c\x0a\x83\x40\x45\xbb\x99\x0a\x41\xf5\xf6\xac\x3a\x3d\xc6\x3a\xbf\xe2\x1d\xa4\xe6\xcb\xde\x47\xa6\x1b\x32\x4a\xa8\xd6\xcf\x6d\xdf\x56\x6c\x1f\xda\x57\xb3\x9e\xe0\x5f\x89\xf7\x7f\x00\x00\x00\xff\xff\xf6\x0e\x88\xb1\x3f\x17\x00\x00"), + compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\xec\x59\xcf\x6f\xeb\x36\x0c\xbe\xe7\xaf\x20\xfc\x76\x68\x0e\xf5\x1b\x76\x2c\x50\x0c\x0f\xc3\x7e\x1c\xba\x61\x68\xd1\x5d\x86\x21\x50\x6d\xc6\x55\x2b\x4b\xae\x44\x27\x0d\xd2\xfc\xef\x83\x6c\xc7\x91\x2d\x27\x91\xd3\xec\xb4\xdc\x12\x99\xfc\x48\x7f\x1f\x4d\xca\xf2\x7a\x0d\x29\xce\xb9\x44\x88\x66\x33\x26\x50\x53\xce\x24\xcb\x50\x47\xb0\xd9\x7c\x73\xfe\xaf\xd7\x80\x32\x85\xcd\x66\xb2\xd7\xe5\xf1\xfe\xce\x7a\xad\xd7\x10\xff\xfc\x4e\xa8\x25\x13\x8f\xf7\x77\xb0\xd9\x7c\xfd\xf2\xb5\xb2\x33\x3f\x6a\x4c\x90\x2f\x50\xdf\x5a\xa3\xfb\xe6\x0f\x7c\x40\xa9\xc5\x5b\x89\x7a\x55\xbb\x37\x81\xba\x91\x4c\xf9\xf4\x82\x09\xd9\x08\x7f\x5b\xef\x07\x62\x54\x1a\xf8\x00\x52\x8f\x45\x81\xba\x76\xe5\x73\xc0\xb7\xf6\x62\x34\xe7\x9a\xcb\xcc\xfa\xdc\x58\x9f\xea\x86\x4c\xfc\x4b\xb5\x0a\x1f\x20\x50\xba\x11\xff\x01\x6b\xf4\xab\x56\x65\x71\xc7\x9e\x50\x98\xf8\x41\x69\xc2\xf4\x4f\xc6\xb5\x89\xff\x62\xa2\x44\x1b\xf0\x45\x71\x09\x11\x58\x54\xa8\x43\x66\x04\x57\x16\x2b\xfe\x49\xe5\xb9\x92\xb5\xf3\xb4\x59\x73\xf0\xa6\xb0\xd9\x5c\xad\xd7\xb0\xe4\xf4\xdc\x35\x8e\xef\x31\x57\x0b\xec\x46\xff\x83\xe5\x68\x1a\x46\x87\xa2\xb7\x89\x4f\xdb\x5f\x7b\x64\x4a\xd1\x24\x9a\x17\xc4\x95\x8c\x0e\x70\x4c\xf8\x4e\xb5\xa4\x33\xc1\x0d\x35\xa6\x9a\xc9\x0c\x21\x86\xcd\xa6\xce\xeb\x66\xb2\x5b\xf4\x79\xb2\xac\x5c\x57\x44\xda\xf4\xed\xbf\x5b\x68\x6f\xa0\x49\xac\x0e\xfe\x4d\x4a\x45\xcc\xe6\xd4\x81\x74\x96\x4f\xc3\x7d\x50\xa5\x4e\xf0\xa6\x16\x13\x25\x6a\x46\x4a\xd7\x95\x38\x19\x20\xea\x20\x05\xb3\x9c\xe9\xd7\x54\x2d\xa5\xc7\xc5\x24\x94\x8c\xc0\xac\x27\xe3\xe9\x08\x45\x0e\x22\x64\x32\xcc\x88\x11\x2c\x79\x8d\x53\x9c\xb3\x52\x50\x4c\x9c\x04\x36\x54\x10\xe6\x85\x60\xd4\x7d\x38\xe3\x7d\x35\xd8\xc5\x29\x8d\x6d\x0f\xf9\x10\x54\xb7\x09\x05\xe2\xcd\x99\x10\x4f\x2c\x79\xf5\xf0\x06\xd3\xb7\xa0\xf0\x01\xc7\x0c\x05\x97\xaf\xc1\x19\x24\x4d\x06\x3c\x8d\xc2\x1c\x0a\x8d\xb6\xd6\x02\xad\x9d\x84\x0e\x32\x56\xf5\xe0\xc0\x94\x79\xa2\x24\xe6\xea\x85\x47\xe1\xf6\xa5\x16\xa1\x19\x87\xdf\xdc\x5c\x29\xaa\x27\x8e\x53\x83\xae\x79\x61\x6f\x2d\x2d\x69\xd5\xba\xf8\x0d\x6d\x5c\x39\xfa\x88\x89\xe0\x28\xe9\xf4\x82\xdc\x87\xb8\x9b\x8a\xa7\x69\xe6\xe3\x72\x69\x88\xc9\x04\xcd\x00\xae\xd7\xc1\xe3\xfd\xac\xaa\xc2\x64\x28\x39\xb6\xc0\x39\x1a\xc3\xb2\xd3\x9e\x6f\x0f\xcc\x57\xa8\x19\x78\x7b\x1a\xda\xe0\x84\x9b\xf4\xe6\x6b\x67\x80\x4f\xe1\x7b\xb8\xb6\x8d\xb3\x5a\x84\x7a\xb1\x6a\x9d\x87\x19\xe9\xee\x02\xaa\x20\xd7\xce\x1d\x0d\xc4\xbb\x47\xa3\xc4\x02\xd3\x5e\xc4\xed\x72\x78\xcc\xad\x87\x17\xf5\x3a\x84\x52\x53\xf5\xf1\xf1\xd5\xd4\x51\x7d\x89\xc9\x33\xa3\xb1\x9a\x4f\x2e\xfa\x1d\xd0\xcf\xdd\x28\x3f\x6a\xe1\xe1\x0d\xea\xb3\x47\xf5\x9e\x3e\xa4\x66\x76\x58\xee\xed\xa4\xbe\x79\xc1\x34\xad\x46\xd8\x13\xcb\x42\xad\x59\x86\x92\x66\xfd\x11\xd7\xad\xaf\x05\x4f\x48\x69\x55\x98\x5d\xd9\x12\x23\x9c\x75\x0b\xed\x52\x4b\xe3\x7a\x81\xcf\x2a\x4a\xe2\xb4\x9a\xa5\xdc\x14\x82\xad\x66\x7b\x76\x53\xc7\x1b\xb7\x8f\x9c\x2b\xc9\x49\x59\x42\x66\xa4\x94\x18\x39\x12\x3b\xb3\xab\x34\xcf\x6a\x81\xfa\x0c\xfb\x47\x0f\xea\xbf\xaf\xa7\xf3\x94\x53\x78\x35\x9d\xaf\x98\xfc\x2d\xfd\x21\x26\x77\x7b\xba\x31\x33\xc5\xdd\xcd\x49\xe7\x61\xdf\xbd\xa6\x8f\x7f\x47\x70\x70\x2e\xf2\x8e\x91\xd7\x65\x91\x50\x60\xa6\x59\x3e\x44\xe5\xff\x96\x94\x94\x9b\x44\xe9\x74\xb7\x37\x57\x92\x76\xdb\x7d\xbf\x14\xfb\xf6\xa7\x37\xae\x3e\xd2\x45\x0d\xbb\xad\x78\xc2\xf7\xcb\xa3\xfe\x69\x1e\x73\x43\xc8\x72\xb7\xf9\xe6\x39\xd3\xab\x93\xea\xb4\x8f\x75\x7a\xc5\x7b\x48\xcd\x49\x40\x88\x4c\x5f\x60\x94\x50\xce\xf1\xdc\xa7\x15\x6b\x43\x87\x6a\x36\x10\xfc\x04\xf1\x16\x3f\x9c\x8f\x72\x17\xeb\x42\xfa\x10\xe9\x2f\x5c\xb3\xb3\x3c\x2e\x1d\xa0\xde\x59\xc7\x85\xf3\x49\xf5\x1a\x33\xc8\x55\xa1\xb9\xd2\xdc\xbe\xa1\x5e\x37\x6f\x3b\xdf\x6d\x97\xe0\xe6\x16\xa2\x68\xfb\x12\xb4\x3d\xff\xee\xdc\xad\xf5\x01\x00\xa8\xfc\x0c\x2e\x70\xeb\xc7\x65\x8a\xef\xdb\x23\x78\x88\xb6\x97\xa2\x8e\x07\x9f\xc3\x15\xbe\x39\x8e\x51\xa2\x39\xf1\x84\x89\x68\xda\x1a\xb6\xf0\x6d\x5a\xb7\x10\xfd\xc6\xb3\xe7\x2e\x16\x0a\x83\x15\x20\x93\x69\x1f\x75\xc9\xb4\xe4\x32\x8b\xa6\x70\x25\xd1\x01\xaa\x61\xa6\x47\x62\xfd\x8e\x29\x2f\xf3\xf0\x68\x5c\xce\x95\x0d\x65\x57\x77\xa1\x8e\x86\xb9\x53\xcb\x5e\x0c\x99\xb6\x9a\xb8\xbf\xeb\x6f\x6a\x2e\x74\xc7\xad\xab\x53\x5b\x18\x5e\xec\x51\x6a\x8d\x56\x2c\x40\xb5\xb3\x2b\x17\xa4\xde\xf9\x14\x3c\xae\x62\x5f\xc9\x63\xca\xee\x90\xfa\x57\xdd\x56\xa7\x55\xf2\x8a\xd4\x3d\x36\x3a\x79\x52\x0d\x80\x31\xc1\x99\x39\xfd\xe0\x7d\x5f\x7a\x9f\xfe\x5a\x32\x00\x7c\xf8\x73\xc9\x80\xc3\xb1\x6f\x26\x43\xc9\x7b\x1f\x4e\xfe\x0d\x00\x00\xff\xff\x74\x5d\xc4\xb5\xa5\x1f\x00\x00"), }, "/templates/email.tmpl": &vfsgen۰CompressedFileInfo{ name: "email.tmpl", @@ -305,7 +303,7 @@ func (f *vfsgen۰CompressedFile) Read(p []byte) (n int, err error) { } if f.grPos < f.seekPos { // Fast-forward. - _, err = io.CopyN(ioutil.Discard, f.gr, f.seekPos-f.grPos) + _, err = io.CopyN(io.Discard, f.gr, f.seekPos-f.grPos) if err != nil { return 0, err } diff --git a/vendor/github.com/prometheus/alertmanager/cluster/channel.go b/vendor/github.com/prometheus/alertmanager/cluster/channel.go index ba0b834cd1..e608d464e7 100644 --- a/vendor/github.com/prometheus/alertmanager/cluster/channel.go +++ b/vendor/github.com/prometheus/alertmanager/cluster/channel.go @@ -14,11 +14,10 @@ package cluster import ( + "log/slog" "sync" "time" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/gogo/protobuf/proto" "github.com/hashicorp/memberlist" "github.com/prometheus/client_golang/prometheus" @@ -35,7 +34,7 @@ type Channel struct { sendOversize func(*memberlist.Node, []byte) error msgc chan []byte - logger log.Logger + logger *slog.Logger oversizeGossipMessageFailureTotal prometheus.Counter oversizeGossipMessageDroppedTotal prometheus.Counter @@ -50,7 +49,7 @@ func NewChannel( send func([]byte), peers func() []*memberlist.Node, sendOversize func(*memberlist.Node, []byte) error, - logger log.Logger, + logger *slog.Logger, stopc chan struct{}, reg prometheus.Registerer, ) *Channel { @@ -70,9 +69,13 @@ func NewChannel( ConstLabels: prometheus.Labels{"key": key}, }) oversizeGossipDuration := prometheus.NewHistogram(prometheus.HistogramOpts{ - Name: "alertmanager_oversize_gossip_message_duration_seconds", - Help: "Duration of oversized gossip message requests.", - ConstLabels: prometheus.Labels{"key": key}, + Name: "alertmanager_oversize_gossip_message_duration_seconds", + Help: "Duration of oversized gossip message requests.", + ConstLabels: prometheus.Labels{"key": key}, + Buckets: prometheus.DefBuckets, + NativeHistogramBucketFactor: 1.1, + NativeHistogramMaxBucketNumber: 100, + NativeHistogramMinResetDuration: 1 * time.Hour, }) reg.MustRegister(oversizeGossipDuration, oversizeGossipMessageFailureTotal, oversizeGossipMessageDroppedTotal, oversizeGossipMessageSentTotal) @@ -109,7 +112,7 @@ func (c *Channel) handleOverSizedMessages(stopc chan struct{}) { c.oversizeGossipMessageSentTotal.Inc() start := time.Now() if err := c.sendOversize(n, b); err != nil { - level.Debug(c.logger).Log("msg", "failed to send reliable", "key", c.key, "node", n, "err", err) + c.logger.Debug("failed to send reliable", "key", c.key, "node", n, "err", err) c.oversizeGossipMessageFailureTotal.Inc() return } @@ -135,7 +138,7 @@ func (c *Channel) Broadcast(b []byte) { select { case c.msgc <- b: default: - level.Debug(c.logger).Log("msg", "oversized gossip channel full") + c.logger.Debug("oversized gossip channel full") c.oversizeGossipMessageDroppedTotal.Inc() } } else { diff --git a/vendor/github.com/prometheus/alertmanager/cluster/cluster.go b/vendor/github.com/prometheus/alertmanager/cluster/cluster.go index d85ee7f533..14052b2d9b 100644 --- a/vendor/github.com/prometheus/alertmanager/cluster/cluster.go +++ b/vendor/github.com/prometheus/alertmanager/cluster/cluster.go @@ -17,6 +17,7 @@ import ( "context" "errors" "fmt" + "log/slog" "math/rand" "net" "sort" @@ -25,8 +26,6 @@ import ( "sync" "time" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/hashicorp/memberlist" "github.com/oklog/ulid" "github.com/prometheus/client_golang/prometheus" @@ -42,7 +41,7 @@ type ClusterPeer interface { Peers() []ClusterMember } -// ClusterMember interface that represents node peers in a cluster +// ClusterMember interface that represents node peers in a cluster. type ClusterMember interface { // Name returns the name of the node Name() string @@ -82,7 +81,7 @@ type Peer struct { peerUpdateCounter prometheus.Counter peerJoinCounter prometheus.Counter - logger log.Logger + logger *slog.Logger } // peer is an internal type used for bookkeeping. It holds the state of peers @@ -129,7 +128,7 @@ const ( ) func Create( - l log.Logger, + l *slog.Logger, reg prometheus.Registerer, bindAddr string, advertiseAddr string, @@ -171,19 +170,19 @@ func Create( if err != nil { return nil, fmt.Errorf("resolve peers: %w", err) } - level.Debug(l).Log("msg", "resolved peers to following addresses", "peers", strings.Join(resolvedPeers, ",")) + l.Debug("resolved peers to following addresses", "peers", strings.Join(resolvedPeers, ",")) // Initial validation of user-specified advertise address. addr, err := calculateAdvertiseAddress(bindHost, advertiseHost, allowInsecureAdvertise) if err != nil { - level.Warn(l).Log("err", "couldn't deduce an advertise address: "+err.Error()) + l.Warn("couldn't deduce an advertise address: " + err.Error()) } else if hasNonlocal(resolvedPeers) && isUnroutable(addr.String()) { - level.Warn(l).Log("err", "this node advertises itself on an unroutable address", "addr", addr.String()) - level.Warn(l).Log("err", "this node will be unreachable in the cluster") - level.Warn(l).Log("err", "provide --cluster.advertise-address as a routable IP address or hostname") + l.Warn("this node advertises itself on an unroutable address", "addr", addr.String()) + l.Warn("this node will be unreachable in the cluster") + l.Warn("provide --cluster.advertise-address as a routable IP address or hostname") } else if isAny(bindAddr) && advertiseHost == "" { // memberlist doesn't advertise properly when the bind address is empty or unspecified. - level.Info(l).Log("msg", "setting advertise address explicitly", "addr", addr.String(), "port", bindPort) + l.Info("setting advertise address explicitly", "addr", addr.String(), "port", bindPort) advertiseHost = addr.String() advertisePort = bindPort } @@ -225,7 +224,7 @@ func Create( cfg.TCPTimeout = tcpTimeout cfg.ProbeTimeout = probeTimeout cfg.ProbeInterval = probeInterval - cfg.LogOutput = &logWriter{l: l} + cfg.Logger = slog.NewLogLogger(l.Handler(), slog.LevelDebug) cfg.GossipNodes = retransmit cfg.UDPBufferSize = MaxGossipPacketSize cfg.Label = label @@ -239,7 +238,7 @@ func Create( } if tlsTransportConfig != nil { - level.Info(l).Log("msg", "using TLS for gossip") + l.Info("using TLS for gossip") cfg.Transport, err = NewTLSTransport(context.Background(), l, reg, cfg.BindAddr, cfg.BindPort, tlsTransportConfig) if err != nil { return nil, fmt.Errorf("tls transport: %w", err) @@ -260,12 +259,12 @@ func (p *Peer) Join( ) error { n, err := p.mlist.Join(p.resolvedPeers) if err != nil { - level.Warn(p.logger).Log("msg", "failed to join cluster", "err", err) + p.logger.Warn("failed to join cluster", "err", err) if reconnectInterval != 0 { - level.Info(p.logger).Log("msg", fmt.Sprintf("will retry joining cluster every %v", reconnectInterval.String())) + p.logger.Info(fmt.Sprintf("will retry joining cluster every %v", reconnectInterval.String())) } } else { - level.Debug(p.logger).Log("msg", "joined cluster", "peers", n) + p.logger.Debug("joined cluster", "peers", n) } if reconnectInterval != 0 { @@ -333,14 +332,6 @@ func (p *Peer) setInitialFailed(peers []string, myAddr string) { } } -type logWriter struct { - l log.Logger -} - -func (l *logWriter) Write(b []byte) (int, error) { - return len(b), level.Debug(l.l).Log("memberlist", string(b)) -} - func (p *Peer) register(reg prometheus.Registerer, name string) { peerInfo := prometheus.NewGauge( prometheus.GaugeOpts{ @@ -420,7 +411,7 @@ func (p *Peer) removeFailedPeers(timeout time.Duration) { if pr.leaveTime.Add(timeout).After(now) { keep = append(keep, pr) } else { - level.Debug(p.logger).Log("msg", "failed peer has timed out", "peer", pr.Node, "addr", pr.Address()) + p.logger.Debug("failed peer has timed out", "peer", pr.Node, "addr", pr.Address()) delete(p.peers, pr.Name) } } @@ -433,27 +424,27 @@ func (p *Peer) reconnect() { failedPeers := p.failedPeers p.peerLock.RUnlock() - logger := log.With(p.logger, "msg", "reconnect") + logger := p.logger.With("msg", "reconnect") for _, pr := range failedPeers { // No need to do book keeping on failedPeers here. If a // reconnect is successful, they will be announced in // peerJoin(). if _, err := p.mlist.Join([]string{pr.Address()}); err != nil { p.failedReconnectionsCounter.Inc() - level.Debug(logger).Log("result", "failure", "peer", pr.Node, "addr", pr.Address(), "err", err) + logger.Debug("failure", "peer", pr.Node, "addr", pr.Address(), "err", err) } else { p.reconnectionsCounter.Inc() - level.Debug(logger).Log("result", "success", "peer", pr.Node, "addr", pr.Address()) + logger.Debug("success", "peer", pr.Node, "addr", pr.Address()) } } } func (p *Peer) refresh() { - logger := log.With(p.logger, "msg", "refresh") + logger := p.logger.With("msg", "refresh") resolvedPeers, err := resolvePeers(context.Background(), p.knownPeers, p.advertiseAddr, &net.Resolver{}, false) if err != nil { - level.Debug(logger).Log("peers", p.knownPeers, "err", err) + logger.Debug(fmt.Sprintf("%v", p.knownPeers), "err", err) return } @@ -470,10 +461,10 @@ func (p *Peer) refresh() { if !isPeerFound { if _, err := p.mlist.Join([]string{peer}); err != nil { p.failedRefreshCounter.Inc() - level.Warn(logger).Log("result", "failure", "addr", peer, "err", err) + logger.Warn("failure", "addr", peer, "err", err) } else { p.refreshCounter.Inc() - level.Debug(logger).Log("result", "success", "addr", peer) + logger.Debug("success", "addr", peer) } } } @@ -502,7 +493,7 @@ func (p *Peer) peerJoin(n *memberlist.Node) { p.peerJoinCounter.Inc() if oldStatus == StatusFailed { - level.Debug(p.logger).Log("msg", "peer rejoined", "peer", pr.Node) + p.logger.Debug("peer rejoined", "peer", pr.Node) p.failedPeers = removeOldPeer(p.failedPeers, pr.Address()) } } @@ -524,7 +515,7 @@ func (p *Peer) peerLeave(n *memberlist.Node) { p.peers[n.Address()] = pr p.peerLeaveCounter.Inc() - level.Debug(p.logger).Log("msg", "peer left", "peer", pr.Node) + p.logger.Debug("peer left", "peer", pr.Node) } func (p *Peer) peerUpdate(n *memberlist.Node) { @@ -542,7 +533,7 @@ func (p *Peer) peerUpdate(n *memberlist.Node) { p.peers[n.Address()] = pr p.peerUpdateCounter.Inc() - level.Debug(p.logger).Log("msg", "peer updated", "peer", pr.Node) + p.logger.Debug("peer updated", "peer", pr.Node) } // AddState adds a new state that will be gossiped. It returns a channel to which @@ -574,7 +565,7 @@ func (p *Peer) AddState(key string, s State, reg prometheus.Registerer) ClusterC // Leave the cluster, waiting up to timeout. func (p *Peer) Leave(timeout time.Duration) error { close(p.stopc) - level.Debug(p.logger).Log("msg", "leaving cluster") + p.logger.Debug("leaving cluster") return p.mlist.Leave(timeout) } @@ -639,10 +630,10 @@ type Member struct { node *memberlist.Node } -// Name implements cluster.ClusterMember +// Name implements cluster.ClusterMember. func (m Member) Name() string { return m.node.Name } -// Address implements cluster.ClusterMember +// Address implements cluster.ClusterMember. func (m Member) Address() string { return m.node.Address() } // Peers returns the peers in the cluster. @@ -680,7 +671,7 @@ func (p *Peer) Position() int { // This is especially important for those that do not have persistent storage. func (p *Peer) Settle(ctx context.Context, interval time.Duration) { const NumOkayRequired = 3 - level.Info(p.logger).Log("msg", "Waiting for gossip to settle...", "interval", interval) + p.logger.Info("Waiting for gossip to settle...", "interval", interval) start := time.Now() nPeers := 0 nOkay := 0 @@ -689,7 +680,7 @@ func (p *Peer) Settle(ctx context.Context, interval time.Duration) { select { case <-ctx.Done(): elapsed := time.Since(start) - level.Info(p.logger).Log("msg", "gossip not settled but continuing anyway", "polls", totalPolls, "elapsed", elapsed) + p.logger.Info("gossip not settled but continuing anyway", "polls", totalPolls, "elapsed", elapsed) close(p.readyc) return case <-time.After(interval): @@ -697,15 +688,15 @@ func (p *Peer) Settle(ctx context.Context, interval time.Duration) { elapsed := time.Since(start) n := len(p.Peers()) if nOkay >= NumOkayRequired { - level.Info(p.logger).Log("msg", "gossip settled; proceeding", "elapsed", elapsed) + p.logger.Info("gossip settled; proceeding", "elapsed", elapsed) break } if n == nPeers { nOkay++ - level.Debug(p.logger).Log("msg", "gossip looks settled", "elapsed", elapsed) + p.logger.Debug("gossip looks settled", "elapsed", elapsed) } else { nOkay = 0 - level.Info(p.logger).Log("msg", "gossip not settled", "polls", totalPolls, "before", nPeers, "now", n, "elapsed", elapsed) + p.logger.Info("gossip not settled", "polls", totalPolls, "before", nPeers, "now", n, "elapsed", elapsed) } nPeers = n totalPolls++ diff --git a/vendor/github.com/prometheus/alertmanager/cluster/delegate.go b/vendor/github.com/prometheus/alertmanager/cluster/delegate.go index 9957f69b91..6783002589 100644 --- a/vendor/github.com/prometheus/alertmanager/cluster/delegate.go +++ b/vendor/github.com/prometheus/alertmanager/cluster/delegate.go @@ -14,10 +14,9 @@ package cluster import ( + "log/slog" "time" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/gogo/protobuf/proto" "github.com/hashicorp/memberlist" "github.com/prometheus/client_golang/prometheus" @@ -37,7 +36,7 @@ const ( type delegate struct { *Peer - logger log.Logger + logger *slog.Logger bcast *memberlist.TransmitLimitedQueue messagesReceived *prometheus.CounterVec @@ -49,7 +48,7 @@ type delegate struct { nodePingDuration *prometheus.HistogramVec } -func newDelegate(l log.Logger, reg prometheus.Registerer, p *Peer, retransmit int) *delegate { +func newDelegate(l *slog.Logger, reg prometheus.Registerer, p *Peer, retransmit int) *delegate { bcast := &memberlist.TransmitLimitedQueue{ NumNodes: p.ClusterSize, RetransmitMult: retransmit, @@ -104,9 +103,12 @@ func newDelegate(l log.Logger, reg prometheus.Registerer, p *Peer, retransmit in }, []string{"peer"}, ) nodePingDuration := prometheus.NewHistogramVec(prometheus.HistogramOpts{ - Name: "alertmanager_cluster_pings_seconds", - Help: "Histogram of latencies for ping messages.", - Buckets: []float64{.005, .01, .025, .05, .1, .25, .5}, + Name: "alertmanager_cluster_pings_seconds", + Help: "Histogram of latencies for ping messages.", + Buckets: []float64{.005, .01, .025, .05, .1, .25, .5}, + NativeHistogramBucketFactor: 1.1, + NativeHistogramMaxBucketNumber: 100, + NativeHistogramMinResetDuration: 1 * time.Hour, }, []string{"peer"}, ) @@ -154,7 +156,7 @@ func (d *delegate) NotifyMsg(b []byte) { var p clusterpb.Part if err := proto.Unmarshal(b, &p); err != nil { - level.Warn(d.logger).Log("msg", "decode broadcast", "err", err) + d.logger.Warn("decode broadcast", "err", err) return } @@ -166,7 +168,7 @@ func (d *delegate) NotifyMsg(b []byte) { return } if err := s.Merge(p.Data); err != nil { - level.Warn(d.logger).Log("msg", "merge broadcast", "err", err, "key", p.Key) + d.logger.Warn("merge broadcast", "err", err, "key", p.Key) return } } @@ -192,14 +194,14 @@ func (d *delegate) LocalState(_ bool) []byte { for key, s := range d.states { b, err := s.MarshalBinary() if err != nil { - level.Warn(d.logger).Log("msg", "encode local state", "err", err, "key", key) + d.logger.Warn("encode local state", "err", err, "key", key) return nil } all.Parts = append(all.Parts, clusterpb.Part{Key: key, Data: b}) } b, err := proto.Marshal(all) if err != nil { - level.Warn(d.logger).Log("msg", "encode local state", "err", err) + d.logger.Warn("encode local state", "err", err) return nil } d.messagesSent.WithLabelValues(fullState).Inc() @@ -213,7 +215,7 @@ func (d *delegate) MergeRemoteState(buf []byte, _ bool) { var fs clusterpb.FullState if err := proto.Unmarshal(buf, &fs); err != nil { - level.Warn(d.logger).Log("msg", "merge remote state", "err", err) + d.logger.Warn("merge remote state", "err", err) return } d.mtx.RLock() @@ -221,11 +223,11 @@ func (d *delegate) MergeRemoteState(buf []byte, _ bool) { for _, p := range fs.Parts { s, ok := d.states[p.Key] if !ok { - level.Warn(d.logger).Log("received", "unknown state key", "len", len(buf), "key", p.Key) + d.logger.Warn("unknown state key", "len", len(buf), "key", p.Key) continue } if err := s.Merge(p.Data); err != nil { - level.Warn(d.logger).Log("msg", "merge remote state", "err", err, "key", p.Key) + d.logger.Warn("merge remote state", "err", err, "key", p.Key) return } } @@ -233,19 +235,19 @@ func (d *delegate) MergeRemoteState(buf []byte, _ bool) { // NotifyJoin is called if a peer joins the cluster. func (d *delegate) NotifyJoin(n *memberlist.Node) { - level.Debug(d.logger).Log("received", "NotifyJoin", "node", n.Name, "addr", n.Address()) + d.logger.Debug("NotifyJoin", "node", n.Name, "addr", n.Address()) d.Peer.peerJoin(n) } // NotifyLeave is called if a peer leaves the cluster. func (d *delegate) NotifyLeave(n *memberlist.Node) { - level.Debug(d.logger).Log("received", "NotifyLeave", "node", n.Name, "addr", n.Address()) + d.logger.Debug("NotifyLeave", "node", n.Name, "addr", n.Address()) d.Peer.peerLeave(n) } // NotifyUpdate is called if a cluster peer gets updated. func (d *delegate) NotifyUpdate(n *memberlist.Node) { - level.Debug(d.logger).Log("received", "NotifyUpdate", "node", n.Name, "addr", n.Address()) + d.logger.Debug("NotifyUpdate", "node", n.Name, "addr", n.Address()) d.Peer.peerUpdate(n) } @@ -275,7 +277,7 @@ func (d *delegate) handleQueueDepth() { case <-time.After(15 * time.Minute): n := d.bcast.NumQueued() if n > maxQueueSize { - level.Warn(d.logger).Log("msg", "dropping messages because too many are queued", "current", n, "limit", maxQueueSize) + d.logger.Warn("dropping messages because too many are queued", "current", n, "limit", maxQueueSize) d.bcast.Prune(maxQueueSize) d.messagesPruned.Add(float64(n - maxQueueSize)) } diff --git a/vendor/github.com/prometheus/alertmanager/cluster/tls_transport.go b/vendor/github.com/prometheus/alertmanager/cluster/tls_transport.go index 7e39d6fed8..f7d4b13d1c 100644 --- a/vendor/github.com/prometheus/alertmanager/cluster/tls_transport.go +++ b/vendor/github.com/prometheus/alertmanager/cluster/tls_transport.go @@ -22,12 +22,11 @@ import ( "crypto/tls" "errors" "fmt" + "log/slog" "net" "strings" "time" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/hashicorp/go-sockaddr" "github.com/hashicorp/memberlist" "github.com/prometheus/client_golang/prometheus" @@ -46,7 +45,7 @@ const ( type TLSTransport struct { ctx context.Context cancel context.CancelFunc - logger log.Logger + logger *slog.Logger bindAddr string bindPort int done chan struct{} @@ -71,7 +70,7 @@ type TLSTransport struct { // a free port automatically. func NewTLSTransport( ctx context.Context, - logger log.Logger, + logger *slog.Logger, reg prometheus.Registerer, bindAddr string, bindPort int, @@ -188,7 +187,7 @@ func (t *TLSTransport) StreamCh() <-chan net.Conn { // Shutdown is called when memberlist is shutting down; this gives the // TLS Transport a chance to clean up the listener and other goroutines. func (t *TLSTransport) Shutdown() error { - level.Debug(t.logger).Log("msg", "shutting down tls transport") + t.logger.Debug("shutting down tls transport") t.cancel() err := t.listener.Close() t.connPool.shutdown() @@ -255,7 +254,7 @@ func (t *TLSTransport) listen() { return } t.readErrs.Inc() - level.Debug(t.logger).Log("msg", "error accepting connection", "err", err) + t.logger.Debug("error accepting connection", "err", err) } else { go t.handle(conn) @@ -268,7 +267,7 @@ func (t *TLSTransport) handle(conn net.Conn) { for { packet, err := rcvTLSConn(conn).read() if err != nil { - level.Debug(t.logger).Log("msg", "error reading from connection", "err", err) + t.logger.Debug("error reading from connection", "err", err) t.readErrs.Inc() return } diff --git a/vendor/github.com/prometheus/alertmanager/config/config.go b/vendor/github.com/prometheus/alertmanager/config/config.go index 7f3602e066..b8e484130a 100644 --- a/vendor/github.com/prometheus/alertmanager/config/config.go +++ b/vendor/github.com/prometheus/alertmanager/config/config.go @@ -30,7 +30,7 @@ import ( "github.com/prometheus/common/model" "gopkg.in/yaml.v2" - "github.com/prometheus/alertmanager/matchers/compat" + "github.com/prometheus/alertmanager/matcher/compat" "github.com/prometheus/alertmanager/pkg/labels" "github.com/prometheus/alertmanager/timeinterval" ) @@ -39,6 +39,11 @@ const secretToken = "" var secretTokenJSON string +// MarshalSecretValue if set to true will expose Secret type +// through the marshal interfaces. Useful for outside projects +// that load and marshal the Alertmanager config. +var MarshalSecretValue bool = commoncfg.MarshalSecretValue + func init() { b, err := json.Marshal(secretToken) if err != nil { @@ -52,6 +57,9 @@ type Secret string // MarshalYAML implements the yaml.Marshaler interface for Secret. func (s Secret) MarshalYAML() (interface{}, error) { + if MarshalSecretValue { + return string(s), nil + } if s != "" { return secretToken, nil } @@ -66,6 +74,12 @@ func (s *Secret) UnmarshalYAML(unmarshal func(interface{}) error) error { // MarshalJSON implements the json.Marshaler interface for Secret. func (s Secret) MarshalJSON() ([]byte, error) { + if MarshalSecretValue { + return json.Marshal(string(s)) + } + if len(s) == 0 { + return json.Marshal("") + } return json.Marshal(secretToken) } @@ -130,6 +144,9 @@ type SecretURL URL // MarshalYAML implements the yaml.Marshaler interface for SecretURL. func (s SecretURL) MarshalYAML() (interface{}, error) { if s.URL != nil { + if MarshalSecretValue { + return s.URL.String(), nil + } return secretToken, nil } return nil, nil @@ -153,6 +170,12 @@ func (s *SecretURL) UnmarshalYAML(unmarshal func(interface{}) error) error { // MarshalJSON implements the json.Marshaler interface for SecretURL. func (s SecretURL) MarshalJSON() ([]byte, error) { + if s.URL == nil { + return json.Marshal("") + } + if MarshalSecretValue { + return json.Marshal(s.URL.String()) + } return json.Marshal(secretToken) } @@ -165,7 +188,15 @@ func (s *SecretURL) UnmarshalJSON(data []byte) error { s.URL = &url.URL{} return nil } - return json.Unmarshal(data, (*URL)(s)) + // Redact the secret URL in case of errors + if err := json.Unmarshal(data, (*URL)(s)); err != nil { + if MarshalSecretValue { + return err + } + return errors.New(strings.ReplaceAll(err.Error(), string(data), "[REDACTED]")) + } + + return nil } // Load parses the YAML input s into a Config. @@ -258,6 +289,15 @@ func resolveFilepaths(baseDir string, cfg *Config) { for _, cfg := range receiver.MSTeamsConfigs { cfg.HTTPConfig.SetDirectory(baseDir) } + for _, cfg := range receiver.MSTeamsV2Configs { + cfg.HTTPConfig.SetDirectory(baseDir) + } + for _, cfg := range receiver.JiraConfigs { + cfg.HTTPConfig.SetDirectory(baseDir) + } + for _, cfg := range receiver.RocketchatConfigs { + cfg.HTTPConfig.SetDirectory(baseDir) + } } } @@ -274,7 +314,7 @@ func (mt *MuteTimeInterval) UnmarshalYAML(unmarshal func(interface{}) error) err return err } if mt.Name == "" { - return fmt.Errorf("missing name in mute time interval") + return errors.New("missing name in mute time interval") } return nil } @@ -292,7 +332,7 @@ func (ti *TimeInterval) UnmarshalYAML(unmarshal func(interface{}) error) error { return err } if ti.Name == "" { - return fmt.Errorf("missing name in time interval") + return errors.New("missing name in time interval") } return nil } @@ -338,19 +378,27 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { } if c.Global.SlackAPIURL != nil && len(c.Global.SlackAPIURLFile) > 0 { - return fmt.Errorf("at most one of slack_api_url & slack_api_url_file must be configured") + return errors.New("at most one of slack_api_url & slack_api_url_file must be configured") } if c.Global.OpsGenieAPIKey != "" && len(c.Global.OpsGenieAPIKeyFile) > 0 { - return fmt.Errorf("at most one of opsgenie_api_key & opsgenie_api_key_file must be configured") + return errors.New("at most one of opsgenie_api_key & opsgenie_api_key_file must be configured") } if c.Global.VictorOpsAPIKey != "" && len(c.Global.VictorOpsAPIKeyFile) > 0 { - return fmt.Errorf("at most one of victorops_api_key & victorops_api_key_file must be configured") + return errors.New("at most one of victorops_api_key & victorops_api_key_file must be configured") } if len(c.Global.SMTPAuthPassword) > 0 && len(c.Global.SMTPAuthPasswordFile) > 0 { - return fmt.Errorf("at most one of smtp_auth_password & smtp_auth_password_file must be configured") + return errors.New("at most one of smtp_auth_password & smtp_auth_password_file must be configured") + } + + if c.Global.RocketchatToken != nil && len(c.Global.RocketchatTokenFile) > 0 { + return errors.New("at most one of rocketchat_token & rocketchat_token_file must be configured") + } + + if c.Global.RocketchatTokenID != nil && len(c.Global.RocketchatTokenIDFile) > 0 { + return errors.New("at most one of rocketchat_token_id & rocketchat_token_id_file must be configured") } names := map[string]struct{}{} @@ -365,15 +413,18 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { } } for _, ec := range rcv.EmailConfigs { + if ec.TLSConfig == nil { + ec.TLSConfig = c.Global.SMTPTLSConfig + } if ec.Smarthost.String() == "" { if c.Global.SMTPSmarthost.String() == "" { - return fmt.Errorf("no global SMTP smarthost set") + return errors.New("no global SMTP smarthost set") } ec.Smarthost = c.Global.SMTPSmarthost } if ec.From == "" { if c.Global.SMTPFrom == "" { - return fmt.Errorf("no global SMTP from set") + return errors.New("no global SMTP from set") } ec.From = c.Global.SMTPFrom } @@ -404,7 +455,7 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { } if sc.APIURL == nil && len(sc.APIURLFile) == 0 { if c.Global.SlackAPIURL == nil && len(c.Global.SlackAPIURLFile) == 0 { - return fmt.Errorf("no global Slack API URL set either inline or in a file") + return errors.New("no global Slack API URL set either inline or in a file") } sc.APIURL = c.Global.SlackAPIURL sc.APIURLFile = c.Global.SlackAPIURLFile @@ -421,7 +472,7 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { } if pdc.URL == nil { if c.Global.PagerdutyURL == nil { - return fmt.Errorf("no global PagerDuty URL set") + return errors.New("no global PagerDuty URL set") } pdc.URL = c.Global.PagerdutyURL } @@ -432,7 +483,7 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { } if ogc.APIURL == nil { if c.Global.OpsGenieAPIURL == nil { - return fmt.Errorf("no global OpsGenie URL set") + return errors.New("no global OpsGenie URL set") } ogc.APIURL = c.Global.OpsGenieAPIURL } @@ -441,7 +492,7 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { } if ogc.APIKey == "" && len(ogc.APIKeyFile) == 0 { if c.Global.OpsGenieAPIKey == "" && len(c.Global.OpsGenieAPIKeyFile) == 0 { - return fmt.Errorf("no global OpsGenie API Key set either inline or in a file") + return errors.New("no global OpsGenie API Key set either inline or in a file") } ogc.APIKey = c.Global.OpsGenieAPIKey ogc.APIKeyFile = c.Global.OpsGenieAPIKeyFile @@ -454,21 +505,21 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { if wcc.APIURL == nil { if c.Global.WeChatAPIURL == nil { - return fmt.Errorf("no global Wechat URL set") + return errors.New("no global Wechat URL set") } wcc.APIURL = c.Global.WeChatAPIURL } if wcc.APISecret == "" { if c.Global.WeChatAPISecret == "" { - return fmt.Errorf("no global Wechat ApiSecret set") + return errors.New("no global Wechat ApiSecret set") } wcc.APISecret = c.Global.WeChatAPISecret } if wcc.CorpID == "" { if c.Global.WeChatAPICorpID == "" { - return fmt.Errorf("no global Wechat CorpID set") + return errors.New("no global Wechat CorpID set") } wcc.CorpID = c.Global.WeChatAPICorpID } @@ -483,7 +534,7 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { } if voc.APIURL == nil { if c.Global.VictorOpsAPIURL == nil { - return fmt.Errorf("no global VictorOps URL set") + return errors.New("no global VictorOps URL set") } voc.APIURL = c.Global.VictorOpsAPIURL } @@ -492,7 +543,7 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { } if voc.APIKey == "" && len(voc.APIKeyFile) == 0 { if c.Global.VictorOpsAPIKey == "" && len(c.Global.VictorOpsAPIKeyFile) == 0 { - return fmt.Errorf("no global VictorOps API Key set") + return errors.New("no global VictorOps API Key set") } voc.APIKey = c.Global.VictorOpsAPIKey voc.APIKeyFile = c.Global.VictorOpsAPIKeyFile @@ -516,8 +567,8 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { if discord.HTTPConfig == nil { discord.HTTPConfig = c.Global.HTTPConfig } - if discord.WebhookURL == nil { - return fmt.Errorf("no discord webhook URL provided") + if discord.WebhookURL == nil && len(discord.WebhookURLFile) == 0 { + return errors.New("no discord webhook URL or URLFile provided") } } for _, webex := range rcv.WebexConfigs { @@ -526,7 +577,7 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { } if webex.APIURL == nil { if c.Global.WebexAPIURL == nil { - return fmt.Errorf("no global Webex URL set") + return errors.New("no global Webex URL set") } webex.APIURL = c.Global.WebexAPIURL @@ -536,8 +587,49 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { if msteams.HTTPConfig == nil { msteams.HTTPConfig = c.Global.HTTPConfig } - if msteams.WebhookURL == nil { - return fmt.Errorf("no msteams webhook URL provided") + if msteams.WebhookURL == nil && len(msteams.WebhookURLFile) == 0 { + return errors.New("no msteams webhook URL or URLFile provided") + } + } + for _, msteamsv2 := range rcv.MSTeamsV2Configs { + if msteamsv2.HTTPConfig == nil { + msteamsv2.HTTPConfig = c.Global.HTTPConfig + } + if msteamsv2.WebhookURL == nil && len(msteamsv2.WebhookURLFile) == 0 { + return errors.New("no msteamsv2 webhook URL or URLFile provided") + } + } + for _, jira := range rcv.JiraConfigs { + if jira.HTTPConfig == nil { + jira.HTTPConfig = c.Global.HTTPConfig + } + if jira.APIURL == nil { + if c.Global.JiraAPIURL == nil { + return errors.New("no global Jira Cloud URL set") + } + jira.APIURL = c.Global.JiraAPIURL + } + } + for _, rocketchat := range rcv.RocketchatConfigs { + if rocketchat.HTTPConfig == nil { + rocketchat.HTTPConfig = c.Global.HTTPConfig + } + if rocketchat.APIURL == nil { + rocketchat.APIURL = c.Global.RocketchatAPIURL + } + if rocketchat.TokenID == nil && len(rocketchat.TokenIDFile) == 0 { + if c.Global.RocketchatTokenID == nil && len(c.Global.RocketchatTokenIDFile) == 0 { + return errors.New("no global Rocketchat TokenID set either inline or in a file") + } + rocketchat.TokenID = c.Global.RocketchatTokenID + rocketchat.TokenIDFile = c.Global.RocketchatTokenIDFile + } + if rocketchat.Token == nil && len(rocketchat.TokenFile) == 0 { + if c.Global.RocketchatToken == nil && len(c.Global.RocketchatTokenFile) == 0 { + return errors.New("no global Rocketchat Token set either inline or in a file") + } + rocketchat.Token = c.Global.RocketchatToken + rocketchat.TokenFile = c.Global.RocketchatTokenFile } } @@ -547,20 +639,20 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { // The root route must not have any matchers as it is the fallback node // for all alerts. if c.Route == nil { - return fmt.Errorf("no routes provided") + return errors.New("no routes provided") } if len(c.Route.Receiver) == 0 { - return fmt.Errorf("root route must specify a default receiver") + return errors.New("root route must specify a default receiver") } if len(c.Route.Match) > 0 || len(c.Route.MatchRE) > 0 || len(c.Route.Matchers) > 0 { - return fmt.Errorf("root route must not have any matchers") + return errors.New("root route must not have any matchers") } if len(c.Route.MuteTimeIntervals) > 0 { - return fmt.Errorf("root route must not have any mute time intervals") + return errors.New("root route must not have any mute time intervals") } if len(c.Route.ActiveTimeIntervals) > 0 { - return fmt.Errorf("root route must not have any active time intervals") + return errors.New("root route must not have any active time intervals") } // Validate that all receivers used in the routing tree are defined. @@ -629,18 +721,21 @@ func checkTimeInterval(r *Route, timeIntervals map[string]struct{}) error { // DefaultGlobalConfig returns GlobalConfig with default values. func DefaultGlobalConfig() GlobalConfig { defaultHTTPConfig := commoncfg.DefaultHTTPClientConfig + defaultSMTPTLSConfig := commoncfg.TLSConfig{} + return GlobalConfig{ - ResolveTimeout: model.Duration(5 * time.Minute), - HTTPConfig: &defaultHTTPConfig, - - SMTPHello: "localhost", - SMTPRequireTLS: true, - PagerdutyURL: mustParseURL("https://events.pagerduty.com/v2/enqueue"), - OpsGenieAPIURL: mustParseURL("https://api.opsgenie.com/"), - WeChatAPIURL: mustParseURL("https://qyapi.weixin.qq.com/cgi-bin/"), - VictorOpsAPIURL: mustParseURL("https://alert.victorops.com/integrations/generic/20131114/alert/"), - TelegramAPIUrl: mustParseURL("https://api.telegram.org"), - WebexAPIURL: mustParseURL("https://webexapis.com/v1/messages"), + ResolveTimeout: model.Duration(5 * time.Minute), + HTTPConfig: &defaultHTTPConfig, + SMTPHello: "localhost", + SMTPRequireTLS: true, + SMTPTLSConfig: &defaultSMTPTLSConfig, + PagerdutyURL: mustParseURL("https://events.pagerduty.com/v2/enqueue"), + OpsGenieAPIURL: mustParseURL("https://api.opsgenie.com/"), + WeChatAPIURL: mustParseURL("https://qyapi.weixin.qq.com/cgi-bin/"), + VictorOpsAPIURL: mustParseURL("https://alert.victorops.com/integrations/generic/20131114/alert/"), + TelegramAPIUrl: mustParseURL("https://api.telegram.org"), + WebexAPIURL: mustParseURL("https://webexapis.com/v1/messages"), + RocketchatAPIURL: mustParseURL("https://open.rocket.chat/"), } } @@ -661,7 +756,7 @@ func parseURL(s string) (*URL, error) { return nil, fmt.Errorf("unsupported scheme %q for URL", u.Scheme) } if u.Host == "" { - return nil, fmt.Errorf("missing host for URL") + return nil, errors.New("missing host for URL") } return &URL{u}, nil } @@ -742,29 +837,36 @@ type GlobalConfig struct { HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"` - SMTPFrom string `yaml:"smtp_from,omitempty" json:"smtp_from,omitempty"` - SMTPHello string `yaml:"smtp_hello,omitempty" json:"smtp_hello,omitempty"` - SMTPSmarthost HostPort `yaml:"smtp_smarthost,omitempty" json:"smtp_smarthost,omitempty"` - SMTPAuthUsername string `yaml:"smtp_auth_username,omitempty" json:"smtp_auth_username,omitempty"` - SMTPAuthPassword Secret `yaml:"smtp_auth_password,omitempty" json:"smtp_auth_password,omitempty"` - SMTPAuthPasswordFile string `yaml:"smtp_auth_password_file,omitempty" json:"smtp_auth_password_file,omitempty"` - SMTPAuthSecret Secret `yaml:"smtp_auth_secret,omitempty" json:"smtp_auth_secret,omitempty"` - SMTPAuthIdentity string `yaml:"smtp_auth_identity,omitempty" json:"smtp_auth_identity,omitempty"` - SMTPRequireTLS bool `yaml:"smtp_require_tls" json:"smtp_require_tls,omitempty"` - SlackAPIURL *SecretURL `yaml:"slack_api_url,omitempty" json:"slack_api_url,omitempty"` - SlackAPIURLFile string `yaml:"slack_api_url_file,omitempty" json:"slack_api_url_file,omitempty"` - PagerdutyURL *URL `yaml:"pagerduty_url,omitempty" json:"pagerduty_url,omitempty"` - OpsGenieAPIURL *URL `yaml:"opsgenie_api_url,omitempty" json:"opsgenie_api_url,omitempty"` - OpsGenieAPIKey Secret `yaml:"opsgenie_api_key,omitempty" json:"opsgenie_api_key,omitempty"` - OpsGenieAPIKeyFile string `yaml:"opsgenie_api_key_file,omitempty" json:"opsgenie_api_key_file,omitempty"` - WeChatAPIURL *URL `yaml:"wechat_api_url,omitempty" json:"wechat_api_url,omitempty"` - WeChatAPISecret Secret `yaml:"wechat_api_secret,omitempty" json:"wechat_api_secret,omitempty"` - WeChatAPICorpID string `yaml:"wechat_api_corp_id,omitempty" json:"wechat_api_corp_id,omitempty"` - VictorOpsAPIURL *URL `yaml:"victorops_api_url,omitempty" json:"victorops_api_url,omitempty"` - VictorOpsAPIKey Secret `yaml:"victorops_api_key,omitempty" json:"victorops_api_key,omitempty"` - VictorOpsAPIKeyFile string `yaml:"victorops_api_key_file,omitempty" json:"victorops_api_key_file,omitempty"` - TelegramAPIUrl *URL `yaml:"telegram_api_url,omitempty" json:"telegram_api_url,omitempty"` - WebexAPIURL *URL `yaml:"webex_api_url,omitempty" json:"webex_api_url,omitempty"` + JiraAPIURL *URL `yaml:"jira_api_url,omitempty" json:"jira_api_url,omitempty"` + SMTPFrom string `yaml:"smtp_from,omitempty" json:"smtp_from,omitempty"` + SMTPHello string `yaml:"smtp_hello,omitempty" json:"smtp_hello,omitempty"` + SMTPSmarthost HostPort `yaml:"smtp_smarthost,omitempty" json:"smtp_smarthost,omitempty"` + SMTPAuthUsername string `yaml:"smtp_auth_username,omitempty" json:"smtp_auth_username,omitempty"` + SMTPAuthPassword Secret `yaml:"smtp_auth_password,omitempty" json:"smtp_auth_password,omitempty"` + SMTPAuthPasswordFile string `yaml:"smtp_auth_password_file,omitempty" json:"smtp_auth_password_file,omitempty"` + SMTPAuthSecret Secret `yaml:"smtp_auth_secret,omitempty" json:"smtp_auth_secret,omitempty"` + SMTPAuthIdentity string `yaml:"smtp_auth_identity,omitempty" json:"smtp_auth_identity,omitempty"` + SMTPRequireTLS bool `yaml:"smtp_require_tls" json:"smtp_require_tls,omitempty"` + SMTPTLSConfig *commoncfg.TLSConfig `yaml:"smtp_tls_config,omitempty" json:"smtp_tls_config,omitempty"` + SlackAPIURL *SecretURL `yaml:"slack_api_url,omitempty" json:"slack_api_url,omitempty"` + SlackAPIURLFile string `yaml:"slack_api_url_file,omitempty" json:"slack_api_url_file,omitempty"` + PagerdutyURL *URL `yaml:"pagerduty_url,omitempty" json:"pagerduty_url,omitempty"` + OpsGenieAPIURL *URL `yaml:"opsgenie_api_url,omitempty" json:"opsgenie_api_url,omitempty"` + OpsGenieAPIKey Secret `yaml:"opsgenie_api_key,omitempty" json:"opsgenie_api_key,omitempty"` + OpsGenieAPIKeyFile string `yaml:"opsgenie_api_key_file,omitempty" json:"opsgenie_api_key_file,omitempty"` + WeChatAPIURL *URL `yaml:"wechat_api_url,omitempty" json:"wechat_api_url,omitempty"` + WeChatAPISecret Secret `yaml:"wechat_api_secret,omitempty" json:"wechat_api_secret,omitempty"` + WeChatAPICorpID string `yaml:"wechat_api_corp_id,omitempty" json:"wechat_api_corp_id,omitempty"` + VictorOpsAPIURL *URL `yaml:"victorops_api_url,omitempty" json:"victorops_api_url,omitempty"` + VictorOpsAPIKey Secret `yaml:"victorops_api_key,omitempty" json:"victorops_api_key,omitempty"` + VictorOpsAPIKeyFile string `yaml:"victorops_api_key_file,omitempty" json:"victorops_api_key_file,omitempty"` + TelegramAPIUrl *URL `yaml:"telegram_api_url,omitempty" json:"telegram_api_url,omitempty"` + WebexAPIURL *URL `yaml:"webex_api_url,omitempty" json:"webex_api_url,omitempty"` + RocketchatAPIURL *URL `yaml:"rocketchat_api_url,omitempty" json:"rocketchat_api_url,omitempty"` + RocketchatToken *Secret `yaml:"rocketchat_token,omitempty" json:"rocketchat_token,omitempty"` + RocketchatTokenFile string `yaml:"rocketchat_token_file,omitempty" json:"rocketchat_token_file,omitempty"` + RocketchatTokenID *Secret `yaml:"rocketchat_token_id,omitempty" json:"rocketchat_token_id,omitempty"` + RocketchatTokenIDFile string `yaml:"rocketchat_token_id_file,omitempty" json:"rocketchat_token_id_file,omitempty"` } // UnmarshalYAML implements the yaml.Unmarshaler interface for GlobalConfig. @@ -822,7 +924,7 @@ func (r *Route) UnmarshalYAML(unmarshal func(interface{}) error) error { } if len(r.GroupBy) > 0 && r.GroupByAll { - return fmt.Errorf("cannot have wildcard group_by (`...`) and other other labels at the same time") + return errors.New("cannot have wildcard group_by (`...`) and other other labels at the same time") } groupBy := map[model.LabelName]struct{}{} @@ -835,10 +937,10 @@ func (r *Route) UnmarshalYAML(unmarshal func(interface{}) error) error { } if r.GroupInterval != nil && time.Duration(*r.GroupInterval) == time.Duration(0) { - return fmt.Errorf("group_interval cannot be zero") + return errors.New("group_interval cannot be zero") } if r.RepeatInterval != nil && time.Duration(*r.RepeatInterval) == time.Duration(0) { - return fmt.Errorf("repeat_interval cannot be zero") + return errors.New("repeat_interval cannot be zero") } return nil @@ -866,7 +968,11 @@ type InhibitRule struct { TargetMatchers Matchers `yaml:"target_matchers,omitempty" json:"target_matchers,omitempty"` // A set of labels that must be equal between the source and target alert // for them to be a match. - Equal model.LabelNames `yaml:"equal,omitempty" json:"equal,omitempty"` + Equal model.LabelNames `yaml:"-" json:"-"` + // EqualStr allows us to validate the label depending on whether UTF-8 is + // enabled or disabled. It should be removed when Alertmanager is updated + // to use the validation modes in recent versions of prometheus/common. + EqualStr []string `yaml:"equal,omitempty" json:"equal,omitempty"` } // UnmarshalYAML implements the yaml.Unmarshaler interface for InhibitRule. @@ -888,6 +994,14 @@ func (r *InhibitRule) UnmarshalYAML(unmarshal func(interface{}) error) error { } } + for _, l := range r.EqualStr { + labelName := model.LabelName(l) + if !compat.IsValidLabelName(labelName) { + return fmt.Errorf("invalid label name %q in equal list", l) + } + r.Equal = append(r.Equal, labelName) + } + return nil } @@ -896,19 +1010,22 @@ type Receiver struct { // A unique identifier for this receiver. Name string `yaml:"name" json:"name"` - DiscordConfigs []*DiscordConfig `yaml:"discord_configs,omitempty" json:"discord_configs,omitempty"` - EmailConfigs []*EmailConfig `yaml:"email_configs,omitempty" json:"email_configs,omitempty"` - PagerdutyConfigs []*PagerdutyConfig `yaml:"pagerduty_configs,omitempty" json:"pagerduty_configs,omitempty"` - SlackConfigs []*SlackConfig `yaml:"slack_configs,omitempty" json:"slack_configs,omitempty"` - WebhookConfigs []*WebhookConfig `yaml:"webhook_configs,omitempty" json:"webhook_configs,omitempty"` - OpsGenieConfigs []*OpsGenieConfig `yaml:"opsgenie_configs,omitempty" json:"opsgenie_configs,omitempty"` - WechatConfigs []*WechatConfig `yaml:"wechat_configs,omitempty" json:"wechat_configs,omitempty"` - PushoverConfigs []*PushoverConfig `yaml:"pushover_configs,omitempty" json:"pushover_configs,omitempty"` - VictorOpsConfigs []*VictorOpsConfig `yaml:"victorops_configs,omitempty" json:"victorops_configs,omitempty"` - SNSConfigs []*SNSConfig `yaml:"sns_configs,omitempty" json:"sns_configs,omitempty"` - TelegramConfigs []*TelegramConfig `yaml:"telegram_configs,omitempty" json:"telegram_configs,omitempty"` - WebexConfigs []*WebexConfig `yaml:"webex_configs,omitempty" json:"webex_configs,omitempty"` - MSTeamsConfigs []*MSTeamsConfig `yaml:"msteams_configs,omitempty" json:"msteams_configs,omitempty"` + DiscordConfigs []*DiscordConfig `yaml:"discord_configs,omitempty" json:"discord_configs,omitempty"` + EmailConfigs []*EmailConfig `yaml:"email_configs,omitempty" json:"email_configs,omitempty"` + PagerdutyConfigs []*PagerdutyConfig `yaml:"pagerduty_configs,omitempty" json:"pagerduty_configs,omitempty"` + SlackConfigs []*SlackConfig `yaml:"slack_configs,omitempty" json:"slack_configs,omitempty"` + WebhookConfigs []*WebhookConfig `yaml:"webhook_configs,omitempty" json:"webhook_configs,omitempty"` + OpsGenieConfigs []*OpsGenieConfig `yaml:"opsgenie_configs,omitempty" json:"opsgenie_configs,omitempty"` + WechatConfigs []*WechatConfig `yaml:"wechat_configs,omitempty" json:"wechat_configs,omitempty"` + PushoverConfigs []*PushoverConfig `yaml:"pushover_configs,omitempty" json:"pushover_configs,omitempty"` + VictorOpsConfigs []*VictorOpsConfig `yaml:"victorops_configs,omitempty" json:"victorops_configs,omitempty"` + SNSConfigs []*SNSConfig `yaml:"sns_configs,omitempty" json:"sns_configs,omitempty"` + TelegramConfigs []*TelegramConfig `yaml:"telegram_configs,omitempty" json:"telegram_configs,omitempty"` + WebexConfigs []*WebexConfig `yaml:"webex_configs,omitempty" json:"webex_configs,omitempty"` + MSTeamsConfigs []*MSTeamsConfig `yaml:"msteams_configs,omitempty" json:"msteams_configs,omitempty"` + MSTeamsV2Configs []*MSTeamsV2Config `yaml:"msteamsv2_configs,omitempty" json:"msteamsv2_configs,omitempty"` + JiraConfigs []*JiraConfig `yaml:"jira_configs,omitempty" json:"jira_configs,omitempty"` + RocketchatConfigs []*RocketchatConfig `yaml:"rocketchat_configs,omitempty" json:"rocketchat_configs,omitempty"` } // UnmarshalYAML implements the yaml.Unmarshaler interface for Receiver. @@ -918,7 +1035,7 @@ func (c *Receiver) UnmarshalYAML(unmarshal func(interface{}) error) error { return err } if c.Name == "" { - return fmt.Errorf("missing name in receiver") + return errors.New("missing name in receiver") } return nil } @@ -972,7 +1089,7 @@ func (re Regexp) MarshalYAML() (interface{}, error) { return nil, nil } -// UnmarshalJSON implements the json.Unmarshaler interface for Regexp +// UnmarshalJSON implements the json.Unmarshaler interface for Regexp. func (re *Regexp) UnmarshalJSON(data []byte) error { var s string if err := json.Unmarshal(data, &s); err != nil { diff --git a/vendor/github.com/prometheus/alertmanager/config/coordinator.go b/vendor/github.com/prometheus/alertmanager/config/coordinator.go index 5ee44f81d8..48728c4e76 100644 --- a/vendor/github.com/prometheus/alertmanager/config/coordinator.go +++ b/vendor/github.com/prometheus/alertmanager/config/coordinator.go @@ -16,10 +16,9 @@ package config import ( "crypto/md5" "encoding/binary" + "log/slog" "sync" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" ) @@ -27,7 +26,7 @@ import ( // single configuration. type Coordinator struct { configFilePath string - logger log.Logger + logger *slog.Logger // Protects config and subscribers mutex sync.Mutex @@ -42,7 +41,7 @@ type Coordinator struct { // NewCoordinator returns a new coordinator with the given configuration file // path. It does not yet load the configuration from file. This is done in // `Reload()`. -func NewCoordinator(configFilePath string, r prometheus.Registerer, l log.Logger) *Coordinator { +func NewCoordinator(configFilePath string, r prometheus.Registerer, l *slog.Logger) *Coordinator { c := &Coordinator{ configFilePath: configFilePath, logger: l, @@ -110,27 +109,27 @@ func (c *Coordinator) Reload() error { c.mutex.Lock() defer c.mutex.Unlock() - level.Info(c.logger).Log( - "msg", "Loading configuration file", + c.logger.Info( + "Loading configuration file", "file", c.configFilePath, ) if err := c.loadFromFile(); err != nil { - level.Error(c.logger).Log( - "msg", "Loading configuration file failed", + c.logger.Error( + "Loading configuration file failed", "file", c.configFilePath, "err", err, ) c.configSuccessMetric.Set(0) return err } - level.Info(c.logger).Log( - "msg", "Completed loading of configuration file", + c.logger.Info( + "Completed loading of configuration file", "file", c.configFilePath, ) if err := c.notifySubscribers(); err != nil { - c.logger.Log( - "msg", "one or more config change subscribers failed to apply new config", + c.logger.Error( + "one or more config change subscribers failed to apply new config", "file", c.configFilePath, "err", err, ) diff --git a/vendor/github.com/prometheus/alertmanager/config/notifiers.go b/vendor/github.com/prometheus/alertmanager/config/notifiers.go index d79c8b5057..74c74a92a0 100644 --- a/vendor/github.com/prometheus/alertmanager/config/notifiers.go +++ b/vendor/github.com/prometheus/alertmanager/config/notifiers.go @@ -14,6 +14,7 @@ package config import ( + "errors" "fmt" "net/textproto" "regexp" @@ -22,6 +23,7 @@ import ( "time" commoncfg "github.com/prometheus/common/config" + "github.com/prometheus/common/model" "github.com/prometheus/common/sigv4" ) @@ -97,6 +99,18 @@ var ( CallbackID: `{{ template "slack.default.callbackid" . }}`, Footer: `{{ template "slack.default.footer" . }}`, } + // DefaultRocketchatConfig defines default values for Rocketchat configurations. + DefaultRocketchatConfig = RocketchatConfig{ + NotifierConfig: NotifierConfig{ + VSendResolved: false, + }, + Color: `{{ if eq .Status "firing" }}red{{ else }}green{{ end }}`, + Emoji: `{{ template "rocketchat.default.emoji" . }}`, + IconURL: `{{ template "rocketchat.default.iconurl" . }}`, + Text: `{{ template "rocketchat.default.text" . }}`, + Title: `{{ template "rocketchat.default.title" . }}`, + TitleLink: `{{ template "rocketchat.default.titlelink" . }}`, + } // DefaultOpsGenieConfig defines default values for OpsGenie configurations. DefaultOpsGenieConfig = OpsGenieConfig{ @@ -172,6 +186,23 @@ var ( Summary: `{{ template "msteams.default.summary" . }}`, Text: `{{ template "msteams.default.text" . }}`, } + + DefaultMSTeamsV2Config = MSTeamsV2Config{ + NotifierConfig: NotifierConfig{ + VSendResolved: true, + }, + Title: `{{ template "msteamsv2.default.title" . }}`, + Text: `{{ template "msteamsv2.default.text" . }}`, + } + + DefaultJiraConfig = JiraConfig{ + NotifierConfig: NotifierConfig{ + VSendResolved: true, + }, + Summary: `{{ template "jira.default.summary" . }}`, + Description: `{{ template "jira.default.description" . }}`, + Priority: `{{ template "jira.default.priority" . }}`, + } ) // NotifierConfig contains base options common across all notifier configurations. @@ -202,11 +233,11 @@ func (c *WebexConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { } if c.RoomID == "" { - return fmt.Errorf("missing room_id on webex_config") + return errors.New("missing room_id on webex_config") } if c.HTTPConfig == nil || c.HTTPConfig.Authorization == nil { - return fmt.Errorf("missing webex_configs.http_config.authorization") + return errors.New("missing webex_configs.http_config.authorization") } return nil @@ -220,8 +251,11 @@ type DiscordConfig struct { WebhookURL *SecretURL `yaml:"webhook_url,omitempty" json:"webhook_url,omitempty"` WebhookURLFile string `yaml:"webhook_url_file,omitempty" json:"webhook_url_file,omitempty"` - Title string `yaml:"title,omitempty" json:"title,omitempty"` - Message string `yaml:"message,omitempty" json:"message,omitempty"` + Content string `yaml:"content,omitempty" json:"content,omitempty"` + Title string `yaml:"title,omitempty" json:"title,omitempty"` + Message string `yaml:"message,omitempty" json:"message,omitempty"` + Username string `yaml:"username,omitempty" json:"username,omitempty"` + AvatarURL string `yaml:"avatar_url,omitempty" json:"avatar_url,omitempty"` } // UnmarshalYAML implements the yaml.Unmarshaler interface. @@ -233,11 +267,11 @@ func (c *DiscordConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { } if c.WebhookURL == nil && c.WebhookURLFile == "" { - return fmt.Errorf("one of webhook_url or webhook_url_file must be configured") + return errors.New("one of webhook_url or webhook_url_file must be configured") } if c.WebhookURL != nil && len(c.WebhookURLFile) > 0 { - return fmt.Errorf("at most one of webhook_url & webhook_url_file must be configured") + return errors.New("at most one of webhook_url & webhook_url_file must be configured") } return nil @@ -248,20 +282,20 @@ type EmailConfig struct { NotifierConfig `yaml:",inline" json:",inline"` // Email address to notify. - To string `yaml:"to,omitempty" json:"to,omitempty"` - From string `yaml:"from,omitempty" json:"from,omitempty"` - Hello string `yaml:"hello,omitempty" json:"hello,omitempty"` - Smarthost HostPort `yaml:"smarthost,omitempty" json:"smarthost,omitempty"` - AuthUsername string `yaml:"auth_username,omitempty" json:"auth_username,omitempty"` - AuthPassword Secret `yaml:"auth_password,omitempty" json:"auth_password,omitempty"` - AuthPasswordFile string `yaml:"auth_password_file,omitempty" json:"auth_password_file,omitempty"` - AuthSecret Secret `yaml:"auth_secret,omitempty" json:"auth_secret,omitempty"` - AuthIdentity string `yaml:"auth_identity,omitempty" json:"auth_identity,omitempty"` - Headers map[string]string `yaml:"headers,omitempty" json:"headers,omitempty"` - HTML string `yaml:"html,omitempty" json:"html,omitempty"` - Text string `yaml:"text,omitempty" json:"text,omitempty"` - RequireTLS *bool `yaml:"require_tls,omitempty" json:"require_tls,omitempty"` - TLSConfig commoncfg.TLSConfig `yaml:"tls_config,omitempty" json:"tls_config,omitempty"` + To string `yaml:"to,omitempty" json:"to,omitempty"` + From string `yaml:"from,omitempty" json:"from,omitempty"` + Hello string `yaml:"hello,omitempty" json:"hello,omitempty"` + Smarthost HostPort `yaml:"smarthost,omitempty" json:"smarthost,omitempty"` + AuthUsername string `yaml:"auth_username,omitempty" json:"auth_username,omitempty"` + AuthPassword Secret `yaml:"auth_password,omitempty" json:"auth_password,omitempty"` + AuthPasswordFile string `yaml:"auth_password_file,omitempty" json:"auth_password_file,omitempty"` + AuthSecret Secret `yaml:"auth_secret,omitempty" json:"auth_secret,omitempty"` + AuthIdentity string `yaml:"auth_identity,omitempty" json:"auth_identity,omitempty"` + Headers map[string]string `yaml:"headers,omitempty" json:"headers,omitempty"` + HTML string `yaml:"html,omitempty" json:"html,omitempty"` + Text string `yaml:"text,omitempty" json:"text,omitempty"` + RequireTLS *bool `yaml:"require_tls,omitempty" json:"require_tls,omitempty"` + TLSConfig *commoncfg.TLSConfig `yaml:"tls_config,omitempty" json:"tls_config,omitempty"` } // UnmarshalYAML implements the yaml.Unmarshaler interface. @@ -272,7 +306,7 @@ func (c *EmailConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { return err } if c.To == "" { - return fmt.Errorf("missing to address in email config") + return errors.New("missing to address in email config") } // Header names are case-insensitive, check for collisions. normalizedHeaders := map[string]string{} @@ -312,13 +346,13 @@ type PagerdutyConfig struct { Group string `yaml:"group,omitempty" json:"group,omitempty"` } -// PagerdutyLink is a link +// PagerdutyLink is a link. type PagerdutyLink struct { Href string `yaml:"href,omitempty" json:"href,omitempty"` Text string `yaml:"text,omitempty" json:"text,omitempty"` } -// PagerdutyImage is an image +// PagerdutyImage is an image. type PagerdutyImage struct { Src string `yaml:"src,omitempty" json:"src,omitempty"` Alt string `yaml:"alt,omitempty" json:"alt,omitempty"` @@ -333,13 +367,13 @@ func (c *PagerdutyConfig) UnmarshalYAML(unmarshal func(interface{}) error) error return err } if c.RoutingKey == "" && c.ServiceKey == "" && c.RoutingKeyFile == "" && c.ServiceKeyFile == "" { - return fmt.Errorf("missing service or routing key in PagerDuty config") + return errors.New("missing service or routing key in PagerDuty config") } if len(c.RoutingKey) > 0 && len(c.RoutingKeyFile) > 0 { - return fmt.Errorf("at most one of routing_key & routing_key_file must be configured") + return errors.New("at most one of routing_key & routing_key_file must be configured") } if len(c.ServiceKey) > 0 && len(c.ServiceKeyFile) > 0 { - return fmt.Errorf("at most one of service_key & service_key_file must be configured") + return errors.New("at most one of service_key & service_key_file must be configured") } if c.Details == nil { c.Details = make(map[string]string) @@ -375,10 +409,10 @@ func (c *SlackAction) UnmarshalYAML(unmarshal func(interface{}) error) error { return err } if c.Type == "" { - return fmt.Errorf("missing type in Slack action configuration") + return errors.New("missing type in Slack action configuration") } if c.Text == "" { - return fmt.Errorf("missing text in Slack action configuration") + return errors.New("missing text in Slack action configuration") } if c.URL != "" { // Clear all message action fields. @@ -388,7 +422,7 @@ func (c *SlackAction) UnmarshalYAML(unmarshal func(interface{}) error) error { } else if c.Name != "" { c.URL = "" } else { - return fmt.Errorf("missing name or url in Slack action configuration") + return errors.New("missing name or url in Slack action configuration") } return nil } @@ -410,7 +444,7 @@ func (c *SlackConfirmationField) UnmarshalYAML(unmarshal func(interface{}) error return err } if c.Text == "" { - return fmt.Errorf("missing text in Slack confirmation configuration") + return errors.New("missing text in Slack confirmation configuration") } return nil } @@ -432,10 +466,10 @@ func (c *SlackField) UnmarshalYAML(unmarshal func(interface{}) error) error { return err } if c.Title == "" { - return fmt.Errorf("missing title in Slack field configuration") + return errors.New("missing title in Slack field configuration") } if c.Value == "" { - return fmt.Errorf("missing value in Slack field configuration") + return errors.New("missing value in Slack field configuration") } return nil } @@ -481,7 +515,7 @@ func (c *SlackConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { } if c.APIURL != nil && len(c.APIURLFile) > 0 { - return fmt.Errorf("at most one of api_url & api_url_file must be configured") + return errors.New("at most one of api_url & api_url_file must be configured") } return nil @@ -501,6 +535,10 @@ type WebhookConfig struct { // Alerts exceeding this threshold will be truncated. Setting this to 0 // allows an unlimited number of alerts. MaxAlerts uint64 `yaml:"max_alerts" json:"max_alerts"` + + // Timeout is the maximum time allowed to invoke the webhook. Setting this to 0 + // does not impose a timeout. + Timeout time.Duration `yaml:"timeout" json:"timeout"` } // UnmarshalYAML implements the yaml.Unmarshaler interface. @@ -511,10 +549,10 @@ func (c *WebhookConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { return err } if c.URL == nil && c.URLFile == "" { - return fmt.Errorf("one of url or url_file must be configured") + return errors.New("one of url or url_file must be configured") } if c.URL != nil && c.URLFile != "" { - return fmt.Errorf("at most one of url & url_file must be configured") + return errors.New("at most one of url & url_file must be configured") } return nil } @@ -594,7 +632,7 @@ func (c *OpsGenieConfig) UnmarshalYAML(unmarshal func(interface{}) error) error } if c.APIKey != "" && len(c.APIKeyFile) > 0 { - return fmt.Errorf("at most one of api_key & api_key_file must be configured") + return errors.New("at most one of api_key & api_key_file must be configured") } for _, r := range c.Responders { @@ -653,10 +691,10 @@ func (c *VictorOpsConfig) UnmarshalYAML(unmarshal func(interface{}) error) error return err } if c.RoutingKey == "" { - return fmt.Errorf("missing Routing key in VictorOps config") + return errors.New("missing Routing key in VictorOps config") } if c.APIKey != "" && len(c.APIKeyFile) > 0 { - return fmt.Errorf("at most one of api_key & api_key_file must be configured") + return errors.New("at most one of api_key & api_key_file must be configured") } reservedFields := []string{"routing_key", "message_type", "state_message", "entity_display_name", "monitoring_tool", "entity_id", "entity_state"} @@ -714,16 +752,16 @@ func (c *PushoverConfig) UnmarshalYAML(unmarshal func(interface{}) error) error return err } if c.UserKey == "" && c.UserKeyFile == "" { - return fmt.Errorf("one of user_key or user_key_file must be configured") + return errors.New("one of user_key or user_key_file must be configured") } if c.UserKey != "" && c.UserKeyFile != "" { - return fmt.Errorf("at most one of user_key & user_key_file must be configured") + return errors.New("at most one of user_key & user_key_file must be configured") } if c.Token == "" && c.TokenFile == "" { - return fmt.Errorf("one of token or token_file must be configured") + return errors.New("one of token or token_file must be configured") } if c.Token != "" && c.TokenFile != "" { - return fmt.Errorf("at most one of token & token_file must be configured") + return errors.New("at most one of token & token_file must be configured") } return nil } @@ -751,7 +789,7 @@ func (c *SNSConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { return err } if (c.TargetARN == "") != (c.TopicARN == "") != (c.PhoneNumber == "") { - return fmt.Errorf("must provide either a Target ARN, Topic ARN, or Phone Number for SNS config") + return errors.New("must provide either a Target ARN, Topic ARN, or Phone Number for SNS config") } return nil } @@ -766,6 +804,7 @@ type TelegramConfig struct { BotToken Secret `yaml:"bot_token,omitempty" json:"token,omitempty"` BotTokenFile string `yaml:"bot_token_file,omitempty" json:"token_file,omitempty"` ChatID int64 `yaml:"chat_id,omitempty" json:"chat,omitempty"` + MessageThreadID int `yaml:"message_thread_id,omitempty" json:"message_thread_id,omitempty"` Message string `yaml:"message,omitempty" json:"message,omitempty"` DisableNotifications bool `yaml:"disable_notifications,omitempty" json:"disable_notifications,omitempty"` ParseMode string `yaml:"parse_mode,omitempty" json:"parse_mode,omitempty"` @@ -779,19 +818,19 @@ func (c *TelegramConfig) UnmarshalYAML(unmarshal func(interface{}) error) error return err } if c.BotToken == "" && c.BotTokenFile == "" { - return fmt.Errorf("missing bot_token or bot_token_file on telegram_config") + return errors.New("missing bot_token or bot_token_file on telegram_config") } if c.BotToken != "" && c.BotTokenFile != "" { - return fmt.Errorf("at most one of bot_token & bot_token_file must be configured") + return errors.New("at most one of bot_token & bot_token_file must be configured") } if c.ChatID == 0 { - return fmt.Errorf("missing chat_id on telegram_config") + return errors.New("missing chat_id on telegram_config") } if c.ParseMode != "" && c.ParseMode != "Markdown" && c.ParseMode != "MarkdownV2" && c.ParseMode != "HTML" { - return fmt.Errorf("unknown parse_mode on telegram_config, must be Markdown, MarkdownV2, HTML or empty string") + return errors.New("unknown parse_mode on telegram_config, must be Markdown, MarkdownV2, HTML or empty string") } return nil } @@ -815,12 +854,145 @@ func (c *MSTeamsConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { } if c.WebhookURL == nil && c.WebhookURLFile == "" { - return fmt.Errorf("one of webhook_url or webhook_url_file must be configured") + return errors.New("one of webhook_url or webhook_url_file must be configured") } if c.WebhookURL != nil && len(c.WebhookURLFile) > 0 { - return fmt.Errorf("at most one of webhook_url & webhook_url_file must be configured") + return errors.New("at most one of webhook_url & webhook_url_file must be configured") } return nil } + +type MSTeamsV2Config struct { + NotifierConfig `yaml:",inline" json:",inline"` + HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"` + WebhookURL *SecretURL `yaml:"webhook_url,omitempty" json:"webhook_url,omitempty"` + WebhookURLFile string `yaml:"webhook_url_file,omitempty" json:"webhook_url_file,omitempty"` + + Title string `yaml:"title,omitempty" json:"title,omitempty"` + Text string `yaml:"text,omitempty" json:"text,omitempty"` +} + +func (c *MSTeamsV2Config) UnmarshalYAML(unmarshal func(interface{}) error) error { + *c = DefaultMSTeamsV2Config + type plain MSTeamsV2Config + if err := unmarshal((*plain)(c)); err != nil { + return err + } + + if c.WebhookURL == nil && c.WebhookURLFile == "" { + return errors.New("one of webhook_url or webhook_url_file must be configured") + } + + if c.WebhookURL != nil && len(c.WebhookURLFile) > 0 { + return errors.New("at most one of webhook_url & webhook_url_file must be configured") + } + + return nil +} + +type JiraConfig struct { + NotifierConfig `yaml:",inline" json:",inline"` + HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"` + + APIURL *URL `yaml:"api_url,omitempty" json:"api_url,omitempty"` + + Project string `yaml:"project,omitempty" json:"project,omitempty"` + Summary string `yaml:"summary,omitempty" json:"summary,omitempty"` + Description string `yaml:"description,omitempty" json:"description,omitempty"` + Labels []string `yaml:"labels,omitempty" json:"labels,omitempty"` + Priority string `yaml:"priority,omitempty" json:"priority,omitempty"` + IssueType string `yaml:"issue_type,omitempty" json:"issue_type,omitempty"` + + ReopenTransition string `yaml:"reopen_transition,omitempty" json:"reopen_transition,omitempty"` + ResolveTransition string `yaml:"resolve_transition,omitempty" json:"resolve_transition,omitempty"` + WontFixResolution string `yaml:"wont_fix_resolution,omitempty" json:"wont_fix_resolution,omitempty"` + ReopenDuration model.Duration `yaml:"reopen_duration,omitempty" json:"reopen_duration,omitempty"` + + Fields map[string]any `yaml:"fields,omitempty" json:"custom_fields,omitempty"` +} + +func (c *JiraConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { + *c = DefaultJiraConfig + type plain JiraConfig + if err := unmarshal((*plain)(c)); err != nil { + return err + } + + if c.Project == "" { + return errors.New("missing project in jira_config") + } + if c.IssueType == "" { + return errors.New("missing issue_type in jira_config") + } + return nil +} + +type RocketchatAttachmentField struct { + Short *bool `json:"short"` + Title string `json:"title,omitempty"` + Value string `json:"value,omitempty"` +} + +const ( + ProcessingTypeSendMessage = "sendMessage" + ProcessingTypeRespondWithMessage = "respondWithMessage" +) + +type RocketchatAttachmentAction struct { + Type string `json:"type,omitempty"` + Text string `json:"text,omitempty"` + URL string `json:"url,omitempty"` + ImageURL string `json:"image_url,omitempty"` + IsWebView bool `json:"is_webview"` + WebviewHeightRatio string `json:"webview_height_ratio,omitempty"` + Msg string `json:"msg,omitempty"` + MsgInChatWindow bool `json:"msg_in_chat_window"` + MsgProcessingType string `json:"msg_processing_type,omitempty"` +} + +// RocketchatConfig configures notifications via Rocketchat. +type RocketchatConfig struct { + NotifierConfig `yaml:",inline" json:",inline"` + + HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"` + + APIURL *URL `yaml:"api_url,omitempty" json:"api_url,omitempty"` + TokenID *Secret `yaml:"token_id,omitempty" json:"token_id,omitempty"` + TokenIDFile string `yaml:"token_id_file,omitempty" json:"token_id_file,omitempty"` + Token *Secret `yaml:"token,omitempty" json:"token,omitempty"` + TokenFile string `yaml:"token_file,omitempty" json:"token_file,omitempty"` + + // RocketChat channel override, (like #other-channel or @username). + Channel string `yaml:"channel,omitempty" json:"channel,omitempty"` + + Color string `yaml:"color,omitempty" json:"color,omitempty"` + Title string `yaml:"title,omitempty" json:"title,omitempty"` + TitleLink string `yaml:"title_link,omitempty" json:"title_link,omitempty"` + Text string `yaml:"text,omitempty" json:"text,omitempty"` + Fields []*RocketchatAttachmentField `yaml:"fields,omitempty" json:"fields,omitempty"` + ShortFields bool `yaml:"short_fields" json:"short_fields,omitempty"` + Emoji string `yaml:"emoji,omitempty" json:"emoji,omitempty"` + IconURL string `yaml:"icon_url,omitempty" json:"icon_url,omitempty"` + ImageURL string `yaml:"image_url,omitempty" json:"image_url,omitempty"` + ThumbURL string `yaml:"thumb_url,omitempty" json:"thumb_url,omitempty"` + LinkNames bool `yaml:"link_names" json:"link_names,omitempty"` + Actions []*RocketchatAttachmentAction `yaml:"actions,omitempty" json:"actions,omitempty"` +} + +// UnmarshalYAML implements the yaml.Unmarshaler interface. +func (c *RocketchatConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { + *c = DefaultRocketchatConfig + type plain RocketchatConfig + if err := unmarshal((*plain)(c)); err != nil { + return err + } + if c.Token != nil && len(c.TokenFile) > 0 { + return errors.New("at most one of token & token_file must be configured") + } + if c.TokenID != nil && len(c.TokenIDFile) > 0 { + return errors.New("at most one of token_id & token_id_file must be configured") + } + return nil +} diff --git a/vendor/github.com/prometheus/alertmanager/dispatch/dispatch.go b/vendor/github.com/prometheus/alertmanager/dispatch/dispatch.go index 640b22abe2..6883786dca 100644 --- a/vendor/github.com/prometheus/alertmanager/dispatch/dispatch.go +++ b/vendor/github.com/prometheus/alertmanager/dispatch/dispatch.go @@ -17,12 +17,11 @@ import ( "context" "errors" "fmt" + "log/slog" "sort" "sync" "time" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/model" @@ -78,6 +77,7 @@ type Dispatcher struct { route *Route alerts provider.Alerts stage notify.Stage + marker types.GroupMarker metrics *DispatcherMetrics limits Limits @@ -91,7 +91,7 @@ type Dispatcher struct { ctx context.Context cancel func() - logger log.Logger + logger *slog.Logger } // Limits describes limits used by Dispatcher. @@ -107,10 +107,10 @@ func NewDispatcher( ap provider.Alerts, r *Route, s notify.Stage, - mk types.Marker, + mk types.GroupMarker, to func(time.Duration) time.Duration, lim Limits, - l log.Logger, + l *slog.Logger, m *DispatcherMetrics, ) *Dispatcher { if lim == nil { @@ -121,8 +121,9 @@ func NewDispatcher( alerts: ap, stage: s, route: r, + marker: mk, timeout: to, - logger: log.With(l, "component", "dispatcher"), + logger: l.With("component", "dispatcher"), metrics: m, limits: lim, } @@ -145,8 +146,8 @@ func (d *Dispatcher) Run() { } func (d *Dispatcher) run(it provider.AlertIterator) { - cleanup := time.NewTicker(30 * time.Second) - defer cleanup.Stop() + maintenance := time.NewTicker(30 * time.Second) + defer maintenance.Stop() defer it.Close() @@ -156,16 +157,16 @@ func (d *Dispatcher) run(it provider.AlertIterator) { if !ok { // Iterator exhausted for some reason. if err := it.Err(); err != nil { - level.Error(d.logger).Log("msg", "Error on alert update", "err", err) + d.logger.Error("Error on alert update", "err", err) } return } - level.Debug(d.logger).Log("msg", "Received alert", "alert", alert) + d.logger.Debug("Received alert", "alert", alert) // Log errors but keep trying. if err := it.Err(); err != nil { - level.Error(d.logger).Log("msg", "Error on alert update", "err", err) + d.logger.Error("Error on alert update", "err", err) continue } @@ -175,33 +176,37 @@ func (d *Dispatcher) run(it provider.AlertIterator) { } d.metrics.processingDuration.Observe(time.Since(now).Seconds()) - case <-cleanup.C: - d.mtx.Lock() - - for _, groups := range d.aggrGroupsPerRoute { - for _, ag := range groups { - if ag.empty() { - ag.stop() - delete(groups, ag.fingerprint()) - d.aggrGroupsNum-- - d.metrics.aggrGroups.Dec() - } - } - } - - d.mtx.Unlock() - + case <-maintenance.C: + d.doMaintenance() case <-d.ctx.Done(): return } } } +func (d *Dispatcher) doMaintenance() { + d.mtx.Lock() + defer d.mtx.Unlock() + for _, groups := range d.aggrGroupsPerRoute { + for _, ag := range groups { + if ag.empty() { + ag.stop() + d.marker.DeleteByGroupKey(ag.routeID, ag.GroupKey()) + delete(groups, ag.fingerprint()) + d.aggrGroupsNum-- + d.metrics.aggrGroups.Dec() + } + } + } +} + // AlertGroup represents how alerts exist within an aggrGroup. type AlertGroup struct { Alerts types.AlertSlice Labels model.LabelSet Receiver string + GroupKey string + RouteID string } type AlertGroups []*AlertGroup @@ -238,6 +243,8 @@ func (d *Dispatcher) Groups(routeFilter func(*Route) bool, alertFilter func(*typ alertGroup := &AlertGroup{ Labels: ag.labels, Receiver: receiver, + GroupKey: ag.GroupKey(), + RouteID: ag.routeID, } alerts := ag.alerts.List() @@ -326,7 +333,7 @@ func (d *Dispatcher) processAlert(alert *types.Alert, route *Route) { // If the group does not exist, create it. But check the limit first. if limit := d.limits.MaxNumberOfAggregationGroups(); limit > 0 && d.aggrGroupsNum >= limit { d.metrics.aggrGroupLimitReached.Inc() - level.Error(d.logger).Log("msg", "Too many aggregation groups, cannot create new group for alert", "groups", d.aggrGroupsNum, "limit", limit, "alert", alert.Name()) + d.logger.Error("Too many aggregation groups, cannot create new group for alert", "groups", d.aggrGroupsNum, "limit", limit, "alert", alert.Name()) return } @@ -343,14 +350,15 @@ func (d *Dispatcher) processAlert(alert *types.Alert, route *Route) { go ag.run(func(ctx context.Context, alerts ...*types.Alert) bool { _, _, err := d.stage.Exec(ctx, d.logger, alerts...) if err != nil { - lvl := level.Error(d.logger) + logger := d.logger.With("num_alerts", len(alerts), "err", err) if errors.Is(ctx.Err(), context.Canceled) { // It is expected for the context to be canceled on // configuration reload or shutdown. In this case, the // message should only be logged at the debug level. - lvl = level.Debug(d.logger) + logger.Debug("Notify for alerts failed") + } else { + logger.Error("Notify for alerts failed") } - lvl.Log("msg", "Notify for alerts failed", "num_alerts", len(alerts), "err", err) } return err == nil }) @@ -373,7 +381,8 @@ func getGroupLabels(alert *types.Alert, route *Route) model.LabelSet { type aggrGroup struct { labels model.LabelSet opts *RouteOpts - logger log.Logger + logger *slog.Logger + routeID string routeKey string alerts *store.Alerts @@ -388,12 +397,13 @@ type aggrGroup struct { } // newAggrGroup returns a new aggregation group. -func newAggrGroup(ctx context.Context, labels model.LabelSet, r *Route, to func(time.Duration) time.Duration, logger log.Logger) *aggrGroup { +func newAggrGroup(ctx context.Context, labels model.LabelSet, r *Route, to func(time.Duration) time.Duration, logger *slog.Logger) *aggrGroup { if to == nil { to = func(d time.Duration) time.Duration { return d } } ag := &aggrGroup{ labels: labels, + routeID: r.ID(), routeKey: r.Key(), opts: &r.RouteOpts, timeout: to, @@ -402,7 +412,7 @@ func newAggrGroup(ctx context.Context, labels model.LabelSet, r *Route, to func( } ag.ctx, ag.cancel = context.WithCancel(ctx) - ag.logger = log.With(logger, "aggrGroup", ag) + ag.logger = logger.With("aggrGroup", ag) // Set an initial one-time wait before flushing // the first batch of notifications. @@ -447,6 +457,7 @@ func (ag *aggrGroup) run(nf notifyFunc) { ctx = notify.WithRepeatInterval(ctx, ag.opts.RepeatInterval) ctx = notify.WithMuteTimeIntervals(ctx, ag.opts.MuteTimeIntervals) ctx = notify.WithActiveTimeIntervals(ctx, ag.opts.ActiveTimeIntervals) + ctx = notify.WithRouteID(ctx, ag.routeID) // Wait the configured interval before calling flush again. ag.mtx.Lock() @@ -476,7 +487,7 @@ func (ag *aggrGroup) stop() { // insert inserts the alert into the aggregation group. func (ag *aggrGroup) insert(alert *types.Alert) { if err := ag.alerts.Set(alert); err != nil { - level.Error(ag.logger).Log("msg", "error on set alert", "err", err) + ag.logger.Error("error on set alert", "err", err) } // Immediately trigger a flush if the wait duration for this @@ -499,38 +510,32 @@ func (ag *aggrGroup) flush(notify func(...*types.Alert) bool) { } var ( - alerts = ag.alerts.List() - alertsSlice = make(types.AlertSlice, 0, len(alerts)) - now = time.Now() + alerts = ag.alerts.List() + alertsSlice = make(types.AlertSlice, 0, len(alerts)) + resolvedSlice = make(types.AlertSlice, 0, len(alerts)) + now = time.Now() ) for _, alert := range alerts { a := *alert // Ensure that alerts don't resolve as time move forwards. - if !a.ResolvedAt(now) { + if a.ResolvedAt(now) { + resolvedSlice = append(resolvedSlice, &a) + } else { a.EndsAt = time.Time{} } alertsSlice = append(alertsSlice, &a) } sort.Stable(alertsSlice) - level.Debug(ag.logger).Log("msg", "flushing", "alerts", fmt.Sprintf("%v", alertsSlice)) + ag.logger.Debug("flushing", "alerts", fmt.Sprintf("%v", alertsSlice)) if notify(alertsSlice...) { - for _, a := range alertsSlice { - // Only delete if the fingerprint has not been inserted - // again since we notified about it. - fp := a.Fingerprint() - got, err := ag.alerts.Get(fp) - if err != nil { - // This should never happen. - level.Error(ag.logger).Log("msg", "failed to get alert", "err", err, "alert", a.String()) - continue - } - if a.Resolved() && got.UpdatedAt == a.UpdatedAt { - if err := ag.alerts.Delete(fp); err != nil { - level.Error(ag.logger).Log("msg", "error on delete alert", "err", err, "alert", a.String()) - } - } + // Delete all resolved alerts as we just sent a notification for them, + // and we don't want to send another one. However, we need to make sure + // that each resolved alert has not fired again during the flush as then + // we would delete an active alert thinking it was resolved. + if err := ag.alerts.DeleteIfNotModified(resolvedSlice); err != nil { + ag.logger.Error("error on delete alerts", "err", err) } } } diff --git a/vendor/github.com/prometheus/alertmanager/dispatch/route.go b/vendor/github.com/prometheus/alertmanager/dispatch/route.go index 5ada178dab..e174672d3f 100644 --- a/vendor/github.com/prometheus/alertmanager/dispatch/route.go +++ b/vendor/github.com/prometheus/alertmanager/dispatch/route.go @@ -17,6 +17,7 @@ import ( "encoding/json" "fmt" "sort" + "strconv" "strings" "time" @@ -184,22 +185,23 @@ func (r *Route) Key() string { func (r *Route) ID() string { b := strings.Builder{} - position := -1 if r.parent != nil { - // Find the position in the same level leaf. - for i, cr := range r.parent.Routes { - if cr == r { - position = i + b.WriteString(r.parent.ID()) + b.WriteRune('/') + } + + b.WriteString(r.Matchers.String()) + + if r.parent != nil { + for i := range r.parent.Routes { + if r == r.parent.Routes[i] { + b.WriteRune('/') + b.WriteString(strconv.Itoa(i)) break } } } - b.WriteString(r.Key()) - if position > -1 { - b.WriteRune('/') - b.WriteString(fmt.Sprint(position)) - } return b.String() } diff --git a/vendor/github.com/prometheus/alertmanager/featurecontrol/featurecontrol.go b/vendor/github.com/prometheus/alertmanager/featurecontrol/featurecontrol.go index 9ff7a2d8fd..1df215acb1 100644 --- a/vendor/github.com/prometheus/alertmanager/featurecontrol/featurecontrol.go +++ b/vendor/github.com/prometheus/alertmanager/featurecontrol/featurecontrol.go @@ -16,35 +16,41 @@ package featurecontrol import ( "errors" "fmt" + "log/slog" "strings" - - "github.com/go-kit/log" - "github.com/go-kit/log/level" ) const ( FeatureReceiverNameInMetrics = "receiver-name-in-metrics" FeatureClassicMode = "classic-mode" FeatureUTF8StrictMode = "utf8-strict-mode" + FeatureAutoGOMEMLIMIT = "auto-gomemlimit" + FeatureAutoGOMAXPROCS = "auto-gomaxprocs" ) var AllowedFlags = []string{ FeatureReceiverNameInMetrics, FeatureClassicMode, FeatureUTF8StrictMode, + FeatureAutoGOMEMLIMIT, + FeatureAutoGOMAXPROCS, } type Flagger interface { EnableReceiverNamesInMetrics() bool ClassicMode() bool UTF8StrictMode() bool + EnableAutoGOMEMLIMIT() bool + EnableAutoGOMAXPROCS() bool } type Flags struct { - logger log.Logger + logger *slog.Logger enableReceiverNamesInMetrics bool classicMode bool utf8StrictMode bool + enableAutoGOMEMLIMIT bool + enableAutoGOMAXPROCS bool } func (f *Flags) EnableReceiverNamesInMetrics() bool { @@ -59,6 +65,14 @@ func (f *Flags) UTF8StrictMode() bool { return f.utf8StrictMode } +func (f *Flags) EnableAutoGOMEMLIMIT() bool { + return f.enableAutoGOMEMLIMIT +} + +func (f *Flags) EnableAutoGOMAXPROCS() bool { + return f.enableAutoGOMAXPROCS +} + type flagOption func(flags *Flags) func enableReceiverNameInMetrics() flagOption { @@ -79,7 +93,19 @@ func enableUTF8StrictMode() flagOption { } } -func NewFlags(logger log.Logger, features string) (Flagger, error) { +func enableAutoGOMEMLIMIT() flagOption { + return func(configs *Flags) { + configs.enableAutoGOMEMLIMIT = true + } +} + +func enableAutoGOMAXPROCS() flagOption { + return func(configs *Flags) { + configs.enableAutoGOMAXPROCS = true + } +} + +func NewFlags(logger *slog.Logger, features string) (Flagger, error) { fc := &Flags{logger: logger} opts := []flagOption{} @@ -91,13 +117,19 @@ func NewFlags(logger log.Logger, features string) (Flagger, error) { switch feature { case FeatureReceiverNameInMetrics: opts = append(opts, enableReceiverNameInMetrics()) - level.Warn(logger).Log("msg", "Experimental receiver name in metrics enabled") + logger.Warn("Experimental receiver name in metrics enabled") case FeatureClassicMode: opts = append(opts, enableClassicMode()) - level.Warn(logger).Log("msg", "Classic mode enabled") + logger.Warn("Classic mode enabled") case FeatureUTF8StrictMode: opts = append(opts, enableUTF8StrictMode()) - level.Warn(logger).Log("msg", "UTF-8 strict mode enabled") + logger.Warn("UTF-8 strict mode enabled") + case FeatureAutoGOMEMLIMIT: + opts = append(opts, enableAutoGOMEMLIMIT()) + logger.Warn("Automatically set GOMEMLIMIT to match the Linux container or system memory limit.") + case FeatureAutoGOMAXPROCS: + opts = append(opts, enableAutoGOMAXPROCS()) + logger.Warn("Automatically set GOMAXPROCS to match Linux container CPU quota") default: return nil, fmt.Errorf("Unknown option '%s' for --enable-feature", feature) } @@ -121,3 +153,7 @@ func (n NoopFlags) EnableReceiverNamesInMetrics() bool { return false } func (n NoopFlags) ClassicMode() bool { return false } func (n NoopFlags) UTF8StrictMode() bool { return false } + +func (n NoopFlags) EnableAutoGOMEMLIMIT() bool { return false } + +func (n NoopFlags) EnableAutoGOMAXPROCS() bool { return false } diff --git a/vendor/github.com/prometheus/alertmanager/inhibit/inhibit.go b/vendor/github.com/prometheus/alertmanager/inhibit/inhibit.go index a8f96f28aa..eb1f7752ea 100644 --- a/vendor/github.com/prometheus/alertmanager/inhibit/inhibit.go +++ b/vendor/github.com/prometheus/alertmanager/inhibit/inhibit.go @@ -15,11 +15,10 @@ package inhibit import ( "context" + "log/slog" "sync" "time" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/oklog/run" "github.com/prometheus/common/model" @@ -36,15 +35,15 @@ import ( type Inhibitor struct { alerts provider.Alerts rules []*InhibitRule - marker types.Marker - logger log.Logger + marker types.AlertMarker + logger *slog.Logger mtx sync.RWMutex cancel func() } // NewInhibitor returns a new Inhibitor. -func NewInhibitor(ap provider.Alerts, rs []config.InhibitRule, mk types.Marker, logger log.Logger) *Inhibitor { +func NewInhibitor(ap provider.Alerts, rs []config.InhibitRule, mk types.AlertMarker, logger *slog.Logger) *Inhibitor { ih := &Inhibitor{ alerts: ap, marker: mk, @@ -67,14 +66,14 @@ func (ih *Inhibitor) run(ctx context.Context) { return case a := <-it.Next(): if err := it.Err(); err != nil { - level.Error(ih.logger).Log("msg", "Error iterating alerts", "err", err) + ih.logger.Error("Error iterating alerts", "err", err) continue } // Update the inhibition rules' cache. for _, r := range ih.rules { if r.SourceMatchers.Matches(a.Labels) { if err := r.scache.Set(a); err != nil { - level.Error(ih.logger).Log("msg", "error on set alert", "err", err) + ih.logger.Error("error on set alert", "err", err) } } } @@ -106,7 +105,7 @@ func (ih *Inhibitor) Run() { }) if err := g.Run(); err != nil { - level.Warn(ih.logger).Log("msg", "error running inhibitor", "err", err) + ih.logger.Warn("error running inhibitor", "err", err) } } diff --git a/vendor/github.com/prometheus/alertmanager/matchers/compat/parse.go b/vendor/github.com/prometheus/alertmanager/matcher/compat/parse.go similarity index 65% rename from vendor/github.com/prometheus/alertmanager/matchers/compat/parse.go rename to vendor/github.com/prometheus/alertmanager/matcher/compat/parse.go index 0c0dfffb1f..667b6cd7cb 100644 --- a/vendor/github.com/prometheus/alertmanager/matchers/compat/parse.go +++ b/vendor/github.com/prometheus/alertmanager/matcher/compat/parse.go @@ -15,23 +15,23 @@ package compat import ( "fmt" + "log/slog" "reflect" "strings" "unicode/utf8" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/prometheus/common/model" + "github.com/prometheus/common/promslog" "github.com/prometheus/alertmanager/featurecontrol" - "github.com/prometheus/alertmanager/matchers/parse" + "github.com/prometheus/alertmanager/matcher/parse" "github.com/prometheus/alertmanager/pkg/labels" ) var ( - isValidLabelName = isValidClassicLabelName(log.NewNopLogger()) - parseMatcher = ClassicMatcherParser(log.NewNopLogger()) - parseMatchers = ClassicMatchersParser(log.NewNopLogger()) + isValidLabelName = isValidClassicLabelName(promslog.NewNopLogger()) + parseMatcher = ClassicMatcherParser(promslog.NewNopLogger()) + parseMatchers = ClassicMatchersParser(promslog.NewNopLogger()) ) // IsValidLabelName returns true if the string is a valid label name. @@ -56,7 +56,7 @@ func Matchers(input, origin string) (labels.Matchers, error) { } // InitFromFlags initializes the compat package from the flagger. -func InitFromFlags(l log.Logger, f featurecontrol.Flagger) { +func InitFromFlags(l *slog.Logger, f featurecontrol.Flagger) { if f.ClassicMode() { isValidLabelName = isValidClassicLabelName(l) parseMatcher = ClassicMatcherParser(l) @@ -74,27 +74,27 @@ func InitFromFlags(l log.Logger, f featurecontrol.Flagger) { // ClassicMatcherParser uses the pkg/labels parser to parse the matcher in // the input string. -func ClassicMatcherParser(l log.Logger) ParseMatcher { +func ClassicMatcherParser(l *slog.Logger) ParseMatcher { return func(input, origin string) (matcher *labels.Matcher, err error) { - level.Debug(l).Log("msg", "Parsing with classic matchers parser", "input", input, "origin", origin) + l.Debug("Parsing with classic matchers parser", "input", input, "origin", origin) return labels.ParseMatcher(input) } } // ClassicMatchersParser uses the pkg/labels parser to parse zero or more // matchers in the input string. It returns an error if the input is invalid. -func ClassicMatchersParser(l log.Logger) ParseMatchers { +func ClassicMatchersParser(l *slog.Logger) ParseMatchers { return func(input, origin string) (matchers labels.Matchers, err error) { - level.Debug(l).Log("msg", "Parsing with classic matchers parser", "input", input, "origin", origin) + l.Debug("Parsing with classic matchers parser", "input", input, "origin", origin) return labels.ParseMatchers(input) } } -// UTF8MatcherParser uses the new matchers/parse parser to parse the matcher +// UTF8MatcherParser uses the new matcher/parse parser to parse the matcher // in the input string. If this fails it does not revert to the pkg/labels parser. -func UTF8MatcherParser(l log.Logger) ParseMatcher { +func UTF8MatcherParser(l *slog.Logger) ParseMatcher { return func(input, origin string) (matcher *labels.Matcher, err error) { - level.Debug(l).Log("msg", "Parsing with UTF-8 matchers parser", "input", input, "origin", origin) + l.Debug("Parsing with UTF-8 matchers parser", "input", input, "origin", origin) if strings.HasPrefix(input, "{") || strings.HasSuffix(input, "}") { return nil, fmt.Errorf("unexpected open or close brace: %s", input) } @@ -102,22 +102,22 @@ func UTF8MatcherParser(l log.Logger) ParseMatcher { } } -// UTF8MatchersParser uses the new matchers/parse parser to parse zero or more +// UTF8MatchersParser uses the new matcher/parse parser to parse zero or more // matchers in the input string. If this fails it does not revert to the // pkg/labels parser. -func UTF8MatchersParser(l log.Logger) ParseMatchers { +func UTF8MatchersParser(l *slog.Logger) ParseMatchers { return func(input, origin string) (matchers labels.Matchers, err error) { - level.Debug(l).Log("msg", "Parsing with UTF-8 matchers parser", "input", input, "origin", origin) + l.Debug("Parsing with UTF-8 matchers parser", "input", input, "origin", origin) return parse.Matchers(input) } } -// FallbackMatcherParser uses the new matchers/parse parser to parse zero or more +// FallbackMatcherParser uses the new matcher/parse parser to parse zero or more // matchers in the string. If this fails it reverts to the pkg/labels parser and // emits a warning log line. -func FallbackMatcherParser(l log.Logger) ParseMatcher { +func FallbackMatcherParser(l *slog.Logger) ParseMatcher { return func(input, origin string) (matcher *labels.Matcher, err error) { - level.Debug(l).Log("msg", "Parsing with UTF-8 matchers parser, with fallback to classic matchers parser", "input", input, "origin", origin) + l.Debug("Parsing with UTF-8 matchers parser, with fallback to classic matchers parser", "input", input, "origin", origin) if strings.HasPrefix(input, "{") || strings.HasSuffix(input, "}") { return nil, fmt.Errorf("unexpected open or close brace: %s", input) } @@ -130,28 +130,28 @@ func FallbackMatcherParser(l log.Logger) ParseMatcher { if cErr != nil { return nil, cErr } - // The input is valid in the pkg/labels parser, but not the matchers/parse + // The input is valid in the pkg/labels parser, but not the matcher/parse // parser. This means the input is not forwards compatible. suggestion := cMatcher.String() - level.Warn(l).Log("msg", "Alertmanager is moving to a new parser for labels and matchers, and this input is incompatible. Alertmanager has instead parsed the input using the classic matchers parser as a fallback. To make this input compatible with the UTF-8 matchers parser please make sure all regular expressions and values are double-quoted. If you are still seeing this message please open an issue.", "input", input, "origin", origin, "err", nErr, "suggestion", suggestion) + l.Warn("Alertmanager is moving to a new parser for labels and matchers, and this input is incompatible. Alertmanager has instead parsed the input using the classic matchers parser as a fallback. To make this input compatible with the UTF-8 matchers parser please make sure all regular expressions and values are double-quoted and backslashes are escaped. If you are still seeing this message please open an issue.", "input", input, "origin", origin, "err", nErr, "suggestion", suggestion) return cMatcher, nil } // If the input is valid in both parsers, but produces different results, // then there is disagreement. if nErr == nil && cErr == nil && !reflect.DeepEqual(nMatcher, cMatcher) { - level.Warn(l).Log("msg", "Matchers input has disagreement", "input", input, "origin", origin) + l.Warn("Matchers input has disagreement", "input", input, "origin", origin) return cMatcher, nil } return nMatcher, nil } } -// FallbackMatchersParser uses the new matchers/parse parser to parse the +// FallbackMatchersParser uses the new matcher/parse parser to parse the // matcher in the input string. If this fails it falls back to the pkg/labels // parser and emits a warning log line. -func FallbackMatchersParser(l log.Logger) ParseMatchers { +func FallbackMatchersParser(l *slog.Logger) ParseMatchers { return func(input, origin string) (matchers labels.Matchers, err error) { - level.Debug(l).Log("msg", "Parsing with UTF-8 matchers parser, with fallback to classic matchers parser", "input", input, "origin", origin) + l.Debug("Parsing with UTF-8 matchers parser, with fallback to classic matchers parser", "input", input, "origin", origin) // Parse the input in both parsers to look for disagreement and incompatible // inputs. nMatchers, nErr := parse.Matchers(input) @@ -161,7 +161,7 @@ func FallbackMatchersParser(l log.Logger) ParseMatchers { if cErr != nil { return nil, cErr } - // The input is valid in the pkg/labels parser, but not the matchers/parse + // The input is valid in the pkg/labels parser, but not the matcher/parse // parser. This means the input is not forwards compatible. var sb strings.Builder for i, n := range cMatchers { @@ -172,15 +172,15 @@ func FallbackMatchersParser(l log.Logger) ParseMatchers { } suggestion := sb.String() // The input is valid in the pkg/labels parser, but not the - // new matchers/parse parser. - level.Warn(l).Log("msg", "Alertmanager is moving to a new parser for labels and matchers, and this input is incompatible. Alertmanager has instead parsed the input using the classic matchers parser as a fallback. To make this input compatible with the UTF-8 matchers parser please make sure all regular expressions and values are double-quoted. If you are still seeing this message please open an issue.", "input", input, "origin", origin, "err", nErr, "suggestion", suggestion) + // new matcher/parse parser. + l.Warn("Alertmanager is moving to a new parser for labels and matchers, and this input is incompatible. Alertmanager has instead parsed the input using the classic matchers parser as a fallback. To make this input compatible with the UTF-8 matchers parser please make sure all regular expressions and values are double-quoted and backslashes are escaped. If you are still seeing this message please open an issue.", "input", input, "origin", origin, "err", nErr, "suggestion", suggestion) return cMatchers, nil } // If the input is valid in both parsers, but produces different results, // then there is disagreement. We need to compare to labels.Matchers(cMatchers) // as cMatchers is a []*labels.Matcher not labels.Matchers. if nErr == nil && cErr == nil && !reflect.DeepEqual(nMatchers, labels.Matchers(cMatchers)) { - level.Warn(l).Log("msg", "Matchers input has disagreement", "input", input, "origin", origin) + l.Warn("Matchers input has disagreement", "input", input, "origin", origin) return cMatchers, nil } return nMatchers, nil @@ -188,14 +188,14 @@ func FallbackMatchersParser(l log.Logger) ParseMatchers { } // isValidClassicLabelName returns true if the string is a valid classic label name. -func isValidClassicLabelName(_ log.Logger) func(model.LabelName) bool { +func isValidClassicLabelName(_ *slog.Logger) func(model.LabelName) bool { return func(name model.LabelName) bool { return name.IsValid() } } // isValidUTF8LabelName returns true if the string is a valid UTF-8 label name. -func isValidUTF8LabelName(_ log.Logger) func(model.LabelName) bool { +func isValidUTF8LabelName(_ *slog.Logger) func(model.LabelName) bool { return func(name model.LabelName) bool { if len(name) == 0 { return false diff --git a/vendor/github.com/prometheus/alertmanager/matchers/parse/lexer.go b/vendor/github.com/prometheus/alertmanager/matcher/parse/lexer.go similarity index 99% rename from vendor/github.com/prometheus/alertmanager/matchers/parse/lexer.go rename to vendor/github.com/prometheus/alertmanager/matcher/parse/lexer.go index d6daa6a9e8..52bb03925e 100644 --- a/vendor/github.com/prometheus/alertmanager/matchers/parse/lexer.go +++ b/vendor/github.com/prometheus/alertmanager/matcher/parse/lexer.go @@ -251,7 +251,7 @@ func (l *lexer) accept(valid string) bool { } // expect consumes the next rune if its one of the valid runes. -// it returns nil if the next rune is valid, otherwise an expectedError +// It returns nil if the next rune is valid, otherwise an expectedError // error. func (l *lexer) expect(valid string) error { if strings.ContainsRune(valid, l.next()) { diff --git a/vendor/github.com/prometheus/alertmanager/matchers/parse/parse.go b/vendor/github.com/prometheus/alertmanager/matcher/parse/parse.go similarity index 98% rename from vendor/github.com/prometheus/alertmanager/matchers/parse/parse.go rename to vendor/github.com/prometheus/alertmanager/matcher/parse/parse.go index 30a95b2554..34e36203c0 100644 --- a/vendor/github.com/prometheus/alertmanager/matchers/parse/parse.go +++ b/vendor/github.com/prometheus/alertmanager/matcher/parse/parse.go @@ -196,7 +196,7 @@ func (p *parser) parseEndOfMatcher(l *lexer) (parseFunc, error) { if err != nil { if errors.Is(err, errEOF) { // If this is the end of input we still need to check if the optional - // open brace has a matching close brace + // open brace has a matching close brace. return p.parseCloseBrace, nil } return nil, fmt.Errorf("%w: %w", err, errExpectedCommaOrCloseBrace) @@ -220,7 +220,7 @@ func (p *parser) parseComma(l *lexer) (parseFunc, error) { if err != nil { if errors.Is(err, errEOF) { // If this is the end of input we still need to check if the optional - // open brace has a matching close brace + // open brace has a matching close brace. return p.parseCloseBrace, nil } return nil, fmt.Errorf("%w: %w", err, errExpectedMatcherOrCloseBrace) @@ -242,6 +242,7 @@ func (p *parser) parseEOF(l *lexer) (parseFunc, error) { return nil, nil } +// nolint:godot // accept returns true if the next token is one of the specified kinds, // otherwise false. If the token is accepted it is consumed. tokenEOF is // not an accepted kind and instead accept returns ErrEOF if there is no @@ -256,6 +257,7 @@ func (p *parser) accept(l *lexer, kinds ...tokenKind) (ok bool, err error) { return ok, err } +// nolint:godot // acceptPeek returns true if the next token is one of the specified kinds, // otherwise false. However, unlike accept, acceptPeek does not consume accepted // tokens. tokenEOF is not an accepted kind and instead accept returns ErrEOF @@ -271,6 +273,7 @@ func (p *parser) acceptPeek(l *lexer, kinds ...tokenKind) (bool, error) { return t.isOneOf(kinds...), nil } +// nolint:godot // expect returns the next token if it is one of the specified kinds, otherwise // it returns an error. If the token is expected it is consumed. tokenEOF is not // an accepted kind and instead expect returns ErrEOF if there is no more input. @@ -285,6 +288,7 @@ func (p *parser) expect(l *lexer, kind ...tokenKind) (token, error) { return t, nil } +// nolint:godot // expect returns the next token if it is one of the specified kinds, otherwise // it returns an error. However, unlike expect, expectPeek does not consume tokens. // tokenEOF is not an accepted kind and instead expect returns ErrEOF if there is no diff --git a/vendor/github.com/prometheus/alertmanager/matchers/parse/token.go b/vendor/github.com/prometheus/alertmanager/matcher/parse/token.go similarity index 100% rename from vendor/github.com/prometheus/alertmanager/matchers/parse/token.go rename to vendor/github.com/prometheus/alertmanager/matcher/parse/token.go diff --git a/vendor/github.com/prometheus/alertmanager/nflog/nflog.go b/vendor/github.com/prometheus/alertmanager/nflog/nflog.go index c533dd0e66..a6c3160880 100644 --- a/vendor/github.com/prometheus/alertmanager/nflog/nflog.go +++ b/vendor/github.com/prometheus/alertmanager/nflog/nflog.go @@ -22,16 +22,16 @@ import ( "errors" "fmt" "io" + "log/slog" "math/rand" "os" "sync" "time" - "github.com/benbjohnson/clock" - "github.com/go-kit/log" - "github.com/go-kit/log/level" + "github.com/coder/quartz" "github.com/matttproud/golang_protobuf_extensions/pbutil" "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/promslog" "github.com/prometheus/alertmanager/cluster" pb "github.com/prometheus/alertmanager/nflog/nflogpb" @@ -46,7 +46,7 @@ var ErrInvalidState = errors.New("invalid state") // query currently allows filtering by and/or receiver group key. // It is configured via QueryParameter functions. // -// TODO(fabxc): Future versions could allow querying a certain receiver +// TODO(fabxc): Future versions could allow querying a certain receiver, // group or a given time interval. type query struct { recv *pb.Receiver @@ -76,9 +76,9 @@ func QGroupKey(gk string) QueryParam { // Log holds the notification log state for alerts that have been notified. type Log struct { - clock clock.Clock + clock quartz.Clock - logger log.Logger + logger *slog.Logger metrics *metrics retention time.Duration @@ -139,8 +139,12 @@ func newMetrics(r prometheus.Registerer) *metrics { Help: "Number notification log received queries that failed.", }) m.queryDuration = prometheus.NewHistogram(prometheus.HistogramOpts{ - Name: "alertmanager_nflog_query_duration_seconds", - Help: "Duration of notification log query evaluation.", + Name: "alertmanager_nflog_query_duration_seconds", + Help: "Duration of notification log query evaluation.", + Buckets: prometheus.DefBuckets, + NativeHistogramBucketFactor: 1.1, + NativeHistogramMaxBucketNumber: 100, + NativeHistogramMinResetDuration: 1 * time.Hour, }) m.propagatedMessagesTotal = prometheus.NewCounter(prometheus.CounterOpts{ Name: "alertmanager_nflog_gossip_messages_propagated_total", @@ -235,7 +239,7 @@ type Options struct { Retention time.Duration - Logger log.Logger + Logger *slog.Logger Metrics prometheus.Registerer } @@ -255,9 +259,9 @@ func New(o Options) (*Log, error) { } l := &Log{ - clock: clock.New(), + clock: quartz.NewReal(), retention: o.Retention, - logger: log.NewNopLogger(), + logger: promslog.NewNopLogger(), st: state{}, broadcast: func([]byte) {}, metrics: newMetrics(o.Metrics), @@ -272,7 +276,7 @@ func New(o Options) (*Log, error) { if !os.IsNotExist(err) { return nil, err } - level.Debug(l.logger).Log("msg", "notification log snapshot file doesn't exist", "err", err) + l.logger.Debug("notification log snapshot file doesn't exist", "err", err) } else { o.SnapshotReader = r defer r.Close() @@ -298,10 +302,10 @@ func (l *Log) now() time.Time { // If not nil, the last argument is an override for what to do as part of the maintenance - for advanced usage. func (l *Log) Maintenance(interval time.Duration, snapf string, stopc <-chan struct{}, override MaintenanceFunc) { if interval == 0 || stopc == nil { - level.Error(l.logger).Log("msg", "interval or stop signal are missing - not running maintenance") + l.logger.Error("interval or stop signal are missing - not running maintenance") return } - t := l.clock.Ticker(interval) + t := l.clock.NewTicker(interval) defer t.Stop() var doMaintenance MaintenanceFunc @@ -331,14 +335,14 @@ func (l *Log) Maintenance(interval time.Duration, snapf string, stopc <-chan str runMaintenance := func(do func() (int64, error)) error { l.metrics.maintenanceTotal.Inc() start := l.now().UTC() - level.Debug(l.logger).Log("msg", "Running maintenance") + l.logger.Debug("Running maintenance") size, err := do() l.metrics.snapshotSize.Set(float64(size)) if err != nil { l.metrics.maintenanceErrorsTotal.Inc() return err } - level.Debug(l.logger).Log("msg", "Maintenance done", "duration", l.now().Sub(start), "size", size) + l.logger.Debug("Maintenance done", "duration", l.now().Sub(start), "size", size) return nil } @@ -349,7 +353,7 @@ Loop: break Loop case <-t.C: if err := runMaintenance(doMaintenance); err != nil { - level.Error(l.logger).Log("msg", "Running maintenance failed", "err", err) + l.logger.Error("Running maintenance failed", "err", err) } } } @@ -359,7 +363,7 @@ Loop: return } if err := runMaintenance(doMaintenance); err != nil { - level.Error(l.logger).Log("msg", "Creating shutdown snapshot failed", "err", err) + l.logger.Error("Creating shutdown snapshot failed", "err", err) } } @@ -530,7 +534,7 @@ func (l *Log) Merge(b []byte) error { // all nodes already. l.broadcast(b) l.metrics.propagatedMessagesTotal.Inc() - level.Debug(l.logger).Log("msg", "gossiping new entry", "entry", e) + l.logger.Debug("gossiping new entry", "entry", e) } } return nil diff --git a/vendor/github.com/prometheus/alertmanager/notify/discord/discord.go b/vendor/github.com/prometheus/alertmanager/notify/discord/discord.go index 69aff39957..42d8724e67 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/discord/discord.go +++ b/vendor/github.com/prometheus/alertmanager/notify/discord/discord.go @@ -18,12 +18,12 @@ import ( "context" "encoding/json" "fmt" + "log/slog" "net/http" + netUrl "net/url" "os" "strings" - "github.com/go-kit/log" - "github.com/go-kit/log/level" commoncfg "github.com/prometheus/common/config" "github.com/prometheus/common/model" @@ -38,6 +38,8 @@ const ( maxTitleLenRunes = 256 // https://discord.com/developers/docs/resources/channel#embed-object-embed-limits - 4096 characters or runes. maxDescriptionLenRunes = 4096 + + maxContentLenRunes = 2000 ) const ( @@ -50,14 +52,14 @@ const ( type Notifier struct { conf *config.DiscordConfig tmpl *template.Template - logger log.Logger + logger *slog.Logger client *http.Client retrier *notify.Retrier webhookURL *config.SecretURL } // New returns a new Discord notifier. -func New(c *config.DiscordConfig, t *template.Template, l log.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { +func New(c *config.DiscordConfig, t *template.Template, l *slog.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { client, err := commoncfg.NewClientFromConfig(*c.HTTPConfig, "discord", httpOpts...) if err != nil { return nil, err @@ -74,8 +76,10 @@ func New(c *config.DiscordConfig, t *template.Template, l log.Logger, httpOpts . } type webhook struct { - Content string `json:"content"` - Embeds []webhookEmbed `json:"embeds"` + Content string `json:"content"` + Embeds []webhookEmbed `json:"embeds"` + Username string `json:"username,omitempty"` + AvatarURL string `json:"avatar_url,omitempty"` } type webhookEmbed struct { @@ -91,7 +95,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) return false, err } - level.Debug(n.logger).Log("incident", key) + n.logger.Debug("extracted group key", "key", key) alerts := types.Alerts(as...) data := notify.GetTemplateData(ctx, n.tmpl, as, n.logger) @@ -105,14 +109,22 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) return false, err } if truncated { - level.Warn(n.logger).Log("msg", "Truncated title", "key", key, "max_runes", maxTitleLenRunes) + n.logger.Warn("Truncated title", "key", key, "max_runes", maxTitleLenRunes) } description, truncated := notify.TruncateInRunes(tmpl(n.conf.Message), maxDescriptionLenRunes) if err != nil { return false, err } if truncated { - level.Warn(n.logger).Log("msg", "Truncated message", "key", key, "max_runes", maxDescriptionLenRunes) + n.logger.Warn("Truncated message", "key", key, "max_runes", maxDescriptionLenRunes) + } + + content, truncated := notify.TruncateInRunes(tmpl(n.conf.Content), maxContentLenRunes) + if err != nil { + return false, err + } + if truncated { + n.logger.Warn("Truncated message", "key", key, "max_runes", maxContentLenRunes) } color := colorGrey @@ -127,14 +139,16 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) if n.conf.WebhookURL != nil { url = n.conf.WebhookURL.String() } else { - content, err := os.ReadFile(n.conf.WebhookURLFile) + b, err := os.ReadFile(n.conf.WebhookURLFile) if err != nil { return false, fmt.Errorf("read webhook_url_file: %w", err) } - url = strings.TrimSpace(string(content)) + url = strings.TrimSpace(string(b)) } w := webhook{ + Content: content, + Username: n.conf.Username, Embeds: []webhookEmbed{{ Title: title, Description: description, @@ -142,6 +156,14 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) }}, } + if len(n.conf.AvatarURL) != 0 { + if _, err := netUrl.Parse(n.conf.AvatarURL); err == nil { + w.AvatarURL = n.conf.AvatarURL + } else { + n.logger.Warn("Bad avatar url", "key", key) + } + } + var payload bytes.Buffer if err = json.NewEncoder(&payload).Encode(w); err != nil { return false, err diff --git a/vendor/github.com/prometheus/alertmanager/notify/email/email.go b/vendor/github.com/prometheus/alertmanager/notify/email/email.go index d7e5be7bdc..7bd910ca6b 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/email/email.go +++ b/vendor/github.com/prometheus/alertmanager/notify/email/email.go @@ -19,6 +19,7 @@ import ( "crypto/tls" "errors" "fmt" + "log/slog" "math/rand" "mime" "mime/multipart" @@ -29,10 +30,9 @@ import ( "net/textproto" "os" "strings" + "sync" "time" - "github.com/go-kit/log" - "github.com/go-kit/log/level" commoncfg "github.com/prometheus/common/config" "github.com/prometheus/alertmanager/config" @@ -45,12 +45,12 @@ import ( type Email struct { conf *config.EmailConfig tmpl *template.Template - logger log.Logger + logger *slog.Logger hostname string } // New returns a new Email notifier. -func New(c *config.EmailConfig, t *template.Template, l log.Logger) *Email { +func New(c *config.EmailConfig, t *template.Template, l *slog.Logger) *Email { if _, ok := c.Headers["Subject"]; !ok { c.Headers["Subject"] = config.DefaultEmailSubject } @@ -75,7 +75,7 @@ func (n *Email) auth(mechs string) (smtp.Auth, error) { // If no username is set, keep going without authentication. if n.conf.AuthUsername == "" { - level.Debug(n.logger).Log("msg", "smtp_auth_username is not configured. Attempting to send email without authenticating") + n.logger.Debug("smtp_auth_username is not configured. Attempting to send email without authenticating") return nil, nil } @@ -131,7 +131,7 @@ func (n *Email) Notify(ctx context.Context, as ...*types.Alert) (bool, error) { success = false ) if n.conf.Smarthost.Port == "465" { - tlsConfig, err := commoncfg.NewTLSConfig(&n.conf.TLSConfig) + tlsConfig, err := commoncfg.NewTLSConfig(n.conf.TLSConfig) if err != nil { return false, fmt.Errorf("parse TLS configuration: %w", err) } @@ -161,7 +161,7 @@ func (n *Email) Notify(ctx context.Context, as ...*types.Alert) (bool, error) { defer func() { // Try to clean up after ourselves but don't log anything if something has failed. if err := c.Quit(); success && err != nil { - level.Warn(n.logger).Log("msg", "failed to close SMTP connection", "err", err) + n.logger.Warn("failed to close SMTP connection", "err", err) } }() @@ -178,7 +178,7 @@ func (n *Email) Notify(ctx context.Context, as ...*types.Alert) (bool, error) { return true, fmt.Errorf("'require_tls' is true (default) but %q does not advertise the STARTTLS extension", n.conf.Smarthost) } - tlsConf, err := commoncfg.NewTLSConfig(&n.conf.TLSConfig) + tlsConf, err := commoncfg.NewTLSConfig(n.conf.TLSConfig) if err != nil { return false, fmt.Errorf("parse TLS configuration: %w", err) } @@ -242,7 +242,15 @@ func (n *Email) Notify(ctx context.Context, as ...*types.Alert) (bool, error) { if err != nil { return true, fmt.Errorf("send DATA command: %w", err) } - defer message.Close() + closeOnce := sync.OnceValue(func() error { + return message.Close() + }) + // Close the message when this method exits in order to not leak resources. Even though we're calling this explicitly + // further down, the method may exit before then. + defer func() { + // If we try close an already-closed writer, it'll send a subsequent request to the server which is invalid. + _ = closeOnce() + }() buffer := &bytes.Buffer{} for header, t := range n.conf.Headers { @@ -331,6 +339,11 @@ func (n *Email) Notify(ctx context.Context, as ...*types.Alert) (bool, error) { return false, fmt.Errorf("write body buffer: %w", err) } + // Complete the message and await response. + if err = closeOnce(); err != nil { + return true, fmt.Errorf("delivery failure: %w", err) + } + success = true return false, nil } @@ -347,7 +360,7 @@ func (a *loginAuth) Start(server *smtp.ServerInfo) (string, []byte, error) { return "LOGIN", []byte{}, nil } -// Used for AUTH LOGIN. (Maybe password should be encrypted) +// Used for AUTH LOGIN. (Maybe password should be encrypted). func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) { if more { switch strings.ToLower(string(fromServer)) { diff --git a/vendor/github.com/prometheus/alertmanager/notify/msteams/msteams.go b/vendor/github.com/prometheus/alertmanager/notify/msteams/msteams.go index d71e108144..f53f020b3b 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/msteams/msteams.go +++ b/vendor/github.com/prometheus/alertmanager/notify/msteams/msteams.go @@ -19,12 +19,11 @@ import ( "encoding/json" "fmt" "io" + "log/slog" "net/http" "os" "strings" - "github.com/go-kit/log" - "github.com/go-kit/log/level" commoncfg "github.com/prometheus/common/config" "github.com/prometheus/common/model" @@ -43,7 +42,7 @@ const ( type Notifier struct { conf *config.MSTeamsConfig tmpl *template.Template - logger log.Logger + logger *slog.Logger client *http.Client retrier *notify.Retrier webhookURL *config.SecretURL @@ -61,7 +60,7 @@ type teamsMessage struct { } // New returns a new notifier that uses the Microsoft Teams Webhook API. -func New(c *config.MSTeamsConfig, t *template.Template, l log.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { +func New(c *config.MSTeamsConfig, t *template.Template, l *slog.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { client, err := commoncfg.NewClientFromConfig(*c.HTTPConfig, "msteams", httpOpts...) if err != nil { return nil, err @@ -86,7 +85,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) return false, err } - level.Debug(n.logger).Log("incident", key) + n.logger.Debug("extracted group key", "key", key) data := notify.GetTemplateData(ctx, n.tmpl, as, n.logger) tmpl := notify.TmplText(n.tmpl, data, &err) diff --git a/vendor/github.com/prometheus/alertmanager/notify/notify.go b/vendor/github.com/prometheus/alertmanager/notify/notify.go index 30861a3027..8fa85c0a21 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/notify.go +++ b/vendor/github.com/prometheus/alertmanager/notify/notify.go @@ -17,14 +17,13 @@ import ( "context" "errors" "fmt" + "log/slog" "sort" "sync" "time" "github.com/cenkalti/backoff/v4" "github.com/cespare/xxhash/v2" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/model" @@ -119,6 +118,7 @@ const ( keyNow keyMuteTimeIntervals keyActiveTimeIntervals + keyRouteID ) // WithReceiverName populates a context with a receiver name. @@ -165,6 +165,10 @@ func WithActiveTimeIntervals(ctx context.Context, at []string) context.Context { return context.WithValue(ctx, keyActiveTimeIntervals, at) } +func WithRouteID(ctx context.Context, routeID string) context.Context { + return context.WithValue(ctx, keyRouteID, routeID) +} + // RepeatInterval extracts a repeat interval from the context. Iff none exists, the // second argument is false. func RepeatInterval(ctx context.Context) (time.Duration, bool) { @@ -228,16 +232,23 @@ func ActiveTimeIntervalNames(ctx context.Context) ([]string, bool) { return v, ok } +// RouteID extracts a RouteID from the context. Iff none exists, the +// // second argument is false. +func RouteID(ctx context.Context) (string, bool) { + v, ok := ctx.Value(keyRouteID).(string) + return v, ok +} + // A Stage processes alerts under the constraints of the given context. type Stage interface { - Exec(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) + Exec(ctx context.Context, l *slog.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) } // StageFunc wraps a function to represent a Stage. -type StageFunc func(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) +type StageFunc func(ctx context.Context, l *slog.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) // Exec implements Stage interface. -func (f StageFunc) Exec(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { +func (f StageFunc) Exec(ctx context.Context, l *slog.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { return f(ctx, l, alerts...) } @@ -288,13 +299,16 @@ func NewMetrics(r prometheus.Registerer, ff featurecontrol.Flagger) *Metrics { numNotificationSuppressedTotal: prometheus.NewCounterVec(prometheus.CounterOpts{ Namespace: "alertmanager", Name: "notifications_suppressed_total", - Help: "The total number of notifications suppressed for being outside of active time intervals or within muted time intervals.", + Help: "The total number of notifications suppressed for being silenced, inhibited, outside of active time intervals or within muted time intervals.", }, []string{"reason"}), notificationLatencySeconds: prometheus.NewHistogramVec(prometheus.HistogramOpts{ - Namespace: "alertmanager", - Name: "notification_latency_seconds", - Help: "The latency of notifications in seconds.", - Buckets: []float64{1, 5, 10, 15, 20}, + Namespace: "alertmanager", + Name: "notification_latency_seconds", + Help: "The latency of notifications in seconds.", + Buckets: []float64{1, 5, 10, 15, 20}, + NativeHistogramBucketFactor: 1.1, + NativeHistogramMaxBucketNumber: 100, + NativeHistogramMinResetDuration: 1 * time.Hour, }, labels), ff: ff, } @@ -350,6 +364,9 @@ func (m *Metrics) InitializeFor(receiver map[string][]Integration) { "discord", "webex", "msteams", + "msteamsv2", + "jira", + "rocketchat", } { m.numNotifications.WithLabelValues(integration) m.numNotificationRequestsTotal.WithLabelValues(integration) @@ -381,6 +398,7 @@ func (pb *PipelineBuilder) New( inhibitor *inhibit.Inhibitor, silencer *silence.Silencer, intervener *timeinterval.Intervener, + marker types.GroupMarker, notificationLog NotificationLog, peer Peer, ) RoutingStage { @@ -388,8 +406,8 @@ func (pb *PipelineBuilder) New( ms := NewGossipSettleStage(peer) is := NewMuteStage(inhibitor, pb.metrics) - tas := NewTimeActiveStage(intervener, pb.metrics) - tms := NewTimeMuteStage(intervener, pb.metrics) + tas := NewTimeActiveStage(intervener, marker, pb.metrics) + tms := NewTimeMuteStage(intervener, marker, pb.metrics) ss := NewMuteStage(silencer, pb.metrics) for name := range receivers { @@ -433,7 +451,7 @@ func createReceiverStage( type RoutingStage map[string]Stage // Exec implements the Stage interface. -func (rs RoutingStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { +func (rs RoutingStage) Exec(ctx context.Context, l *slog.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { receiver, ok := ReceiverName(ctx) if !ok { return ctx, nil, errors.New("receiver missing") @@ -451,7 +469,7 @@ func (rs RoutingStage) Exec(ctx context.Context, l log.Logger, alerts ...*types. type MultiStage []Stage // Exec implements the Stage interface. -func (ms MultiStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { +func (ms MultiStage) Exec(ctx context.Context, l *slog.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { var err error for _, s := range ms { if len(alerts) == 0 { @@ -466,12 +484,12 @@ func (ms MultiStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Al return ctx, alerts, nil } -// FanoutStage executes its stages concurrently +// FanoutStage executes its stages concurrently. type FanoutStage []Stage // Exec attempts to execute all stages concurrently and discards the results. // It returns its input alerts and a types.MultiError if one or more stages fail. -func (fs FanoutStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { +func (fs FanoutStage) Exec(ctx context.Context, l *slog.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { var ( wg sync.WaitGroup me types.MultiError @@ -504,7 +522,7 @@ func NewGossipSettleStage(p Peer) *GossipSettleStage { return &GossipSettleStage{peer: p} } -func (n *GossipSettleStage) Exec(ctx context.Context, _ log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { +func (n *GossipSettleStage) Exec(ctx context.Context, _ *slog.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { if n.peer != nil { if err := n.peer.WaitReady(ctx); err != nil { return ctx, nil, err @@ -514,10 +532,10 @@ func (n *GossipSettleStage) Exec(ctx context.Context, _ log.Logger, alerts ...*t } const ( - suppressedReasonSilence = "silence" - suppressedReasonInhibition = "inhibition" - suppressedReasonMuteTimeInterval = "mute_time_interval" - suppressedReasonActiveTimeInterval = "active_time_interval" + SuppressedReasonSilence = "silence" + SuppressedReasonInhibition = "inhibition" + SuppressedReasonMuteTimeInterval = "mute_time_interval" + SuppressedReasonActiveTimeInterval = "active_time_interval" ) // MuteStage filters alerts through a Muter. @@ -532,7 +550,7 @@ func NewMuteStage(m types.Muter, metrics *Metrics) *MuteStage { } // Exec implements the Stage interface. -func (n *MuteStage) Exec(ctx context.Context, logger log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { +func (n *MuteStage) Exec(ctx context.Context, logger *slog.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { var ( filtered []*types.Alert muted []*types.Alert @@ -548,17 +566,17 @@ func (n *MuteStage) Exec(ctx context.Context, logger log.Logger, alerts ...*type // TODO(fabxc): increment muted alerts counter if muted. } if len(muted) > 0 { - level.Debug(logger).Log("msg", "Notifications will not be sent for muted alerts", "alerts", fmt.Sprintf("%v", muted)) var reason string switch n.muter.(type) { case *silence.Silencer: - reason = suppressedReasonSilence + reason = SuppressedReasonSilence case *inhibit.Inhibitor: - reason = suppressedReasonInhibition + reason = SuppressedReasonInhibition default: } n.metrics.numNotificationSuppressedTotal.WithLabelValues(reason).Add(float64(len(muted))) + logger.Debug("Notifications will not be sent for muted alerts", "alerts", fmt.Sprintf("%v", muted), "reason", reason) } return ctx, filtered, nil @@ -578,7 +596,7 @@ func NewWaitStage(wait func() time.Duration) *WaitStage { } // Exec implements the Stage interface. -func (ws *WaitStage) Exec(ctx context.Context, _ log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { +func (ws *WaitStage) Exec(ctx context.Context, _ *slog.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { select { case <-time.After(ws.wait()): case <-ctx.Done(): @@ -613,7 +631,7 @@ func utcNow() time.Time { return time.Now().UTC() } -// Wrap a slice in a struct so we can store a pointer in sync.Pool +// Wrap a slice in a struct so we can store a pointer in sync.Pool. type hashBuffer struct { buf []byte } @@ -679,7 +697,7 @@ func (n *DedupStage) needsUpdate(entry *nflogpb.Entry, firing, resolved map[uint } // Exec implements the Stage interface. -func (n *DedupStage) Exec(ctx context.Context, _ log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { +func (n *DedupStage) Exec(ctx context.Context, _ *slog.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { gkey, ok := GroupKey(ctx) if !ok { return ctx, nil, errors.New("group key missing") @@ -755,7 +773,7 @@ func NewRetryStage(i Integration, groupName string, metrics *Metrics) *RetryStag } } -func (r RetryStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { +func (r RetryStage) Exec(ctx context.Context, l *slog.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { r.metrics.numNotifications.WithLabelValues(r.labelValues...).Inc() ctx, alerts, err := r.exec(ctx, l, alerts...) @@ -770,7 +788,7 @@ func (r RetryStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Ale return ctx, alerts, err } -func (r RetryStage) exec(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { +func (r RetryStage) exec(ctx context.Context, l *slog.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { var sent []*types.Alert // If we shouldn't send notifications for resolved alerts, but there are only @@ -804,9 +822,9 @@ func (r RetryStage) exec(ctx context.Context, l log.Logger, alerts ...*types.Ale iErr error ) - l = log.With(l, "receiver", r.groupName, "integration", r.integration.String()) + l = l.With("receiver", r.groupName, "integration", r.integration.String()) if groupKey, ok := GroupKey(ctx); ok { - l = log.With(l, "aggrGroup", groupKey) + l = l.With("aggrGroup", groupKey) } for { @@ -845,19 +863,21 @@ func (r RetryStage) exec(ctx context.Context, l log.Logger, alerts ...*types.Ale if ctx.Err() == nil { if iErr == nil || err.Error() != iErr.Error() { // Log the error if the context isn't done and the error isn't the same as before. - level.Warn(l).Log("msg", "Notify attempt failed, will retry later", "attempts", i, "err", err) + l.Warn("Notify attempt failed, will retry later", "attempts", i, "err", err) } // Save this error to be able to return the last seen error by an // integration upon context timeout. iErr = err } } else { - lvl := level.Info(l) + l := l.With("attempts", i, "duration", dur) if i <= 1 { - lvl = level.Debug(log.With(l, "alerts", fmt.Sprintf("%v", alerts))) + l = l.With("alerts", fmt.Sprintf("%v", alerts)) + l.Debug("Notify success") + } else { + l.Info("Notify success") } - lvl.Log("msg", "Notify success", "attempts", i, "duration", dur) return ctx, alerts, nil } case <-ctx.Done(): @@ -893,7 +913,7 @@ func NewSetNotifiesStage(l NotificationLog, recv *nflogpb.Receiver) *SetNotifies } // Exec implements the Stage interface. -func (n SetNotifiesStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { +func (n SetNotifiesStage) Exec(ctx context.Context, l *slog.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { gkey, ok := GroupKey(ctx) if !ok { return ctx, nil, errors.New("group key missing") @@ -920,18 +940,29 @@ func (n SetNotifiesStage) Exec(ctx context.Context, l log.Logger, alerts ...*typ type timeStage struct { muter types.TimeMuter + marker types.GroupMarker metrics *Metrics } type TimeMuteStage timeStage -func NewTimeMuteStage(m types.TimeMuter, metrics *Metrics) *TimeMuteStage { - return &TimeMuteStage{m, metrics} +func NewTimeMuteStage(muter types.TimeMuter, marker types.GroupMarker, metrics *Metrics) *TimeMuteStage { + return &TimeMuteStage{muter, marker, metrics} } // Exec implements the stage interface for TimeMuteStage. // TimeMuteStage is responsible for muting alerts whose route is not in an active time. -func (tms TimeMuteStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { +func (tms TimeMuteStage) Exec(ctx context.Context, l *slog.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { + routeID, ok := RouteID(ctx) + if !ok { + return ctx, nil, errors.New("route ID missing") + } + + gkey, ok := GroupKey(ctx) + if !ok { + return ctx, nil, errors.New("group key missing") + } + muteTimeIntervalNames, ok := MuteTimeIntervalNames(ctx) if !ok { return ctx, alerts, nil @@ -946,29 +977,42 @@ func (tms TimeMuteStage) Exec(ctx context.Context, l log.Logger, alerts ...*type return ctx, alerts, nil } - muted, err := tms.muter.Mutes(muteTimeIntervalNames, now) + muted, mutedBy, err := tms.muter.Mutes(muteTimeIntervalNames, now) if err != nil { return ctx, alerts, err } + // If muted is false then mutedBy is nil and the muted marker is removed. + tms.marker.SetMuted(routeID, gkey, mutedBy) // If the current time is inside a mute time, all alerts are removed from the pipeline. if muted { - tms.metrics.numNotificationSuppressedTotal.WithLabelValues(suppressedReasonMuteTimeInterval).Add(float64(len(alerts))) - level.Debug(l).Log("msg", "Notifications not sent, route is within mute time", "alerts", len(alerts)) + tms.metrics.numNotificationSuppressedTotal.WithLabelValues(SuppressedReasonMuteTimeInterval).Add(float64(len(alerts))) + l.Debug("Notifications not sent, route is within mute time", "alerts", len(alerts)) return ctx, nil, nil } + return ctx, alerts, nil } type TimeActiveStage timeStage -func NewTimeActiveStage(m types.TimeMuter, metrics *Metrics) *TimeActiveStage { - return &TimeActiveStage{m, metrics} +func NewTimeActiveStage(muter types.TimeMuter, marker types.GroupMarker, metrics *Metrics) *TimeActiveStage { + return &TimeActiveStage{muter, marker, metrics} } // Exec implements the stage interface for TimeActiveStage. // TimeActiveStage is responsible for muting alerts whose route is not in an active time. -func (tas TimeActiveStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { +func (tas TimeActiveStage) Exec(ctx context.Context, l *slog.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { + routeID, ok := RouteID(ctx) + if !ok { + return ctx, nil, errors.New("route ID missing") + } + + gkey, ok := GroupKey(ctx) + if !ok { + return ctx, nil, errors.New("group key missing") + } + activeTimeIntervalNames, ok := ActiveTimeIntervalNames(ctx) if !ok { return ctx, alerts, nil @@ -984,15 +1028,24 @@ func (tas TimeActiveStage) Exec(ctx context.Context, l log.Logger, alerts ...*ty return ctx, alerts, errors.New("missing now timestamp") } - muted, err := tas.muter.Mutes(activeTimeIntervalNames, now) + active, _, err := tas.muter.Mutes(activeTimeIntervalNames, now) if err != nil { return ctx, alerts, err } + var mutedBy []string + if !active { + // If the group is muted, then it must be muted by all active time intervals. + // Otherwise, the group must be in at least one active time interval for it + // to be active. + mutedBy = activeTimeIntervalNames + } + tas.marker.SetMuted(routeID, gkey, mutedBy) + // If the current time is not inside an active time, all alerts are removed from the pipeline - if !muted { - tas.metrics.numNotificationSuppressedTotal.WithLabelValues(suppressedReasonActiveTimeInterval).Add(float64(len(alerts))) - level.Debug(l).Log("msg", "Notifications not sent, route is not within active time", "alerts", len(alerts)) + if !active { + tas.metrics.numNotificationSuppressedTotal.WithLabelValues(SuppressedReasonActiveTimeInterval).Add(float64(len(alerts))) + l.Debug("Notifications not sent, route is not within active time", "alerts", len(alerts)) return ctx, nil, nil } diff --git a/vendor/github.com/prometheus/alertmanager/notify/opsgenie/opsgenie.go b/vendor/github.com/prometheus/alertmanager/notify/opsgenie/opsgenie.go index 4421cd6545..7554984639 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/opsgenie/opsgenie.go +++ b/vendor/github.com/prometheus/alertmanager/notify/opsgenie/opsgenie.go @@ -18,12 +18,11 @@ import ( "context" "encoding/json" "fmt" + "log/slog" "net/http" "os" "strings" - "github.com/go-kit/log" - "github.com/go-kit/log/level" commoncfg "github.com/prometheus/common/config" "github.com/prometheus/common/model" @@ -40,13 +39,13 @@ const maxMessageLenRunes = 130 type Notifier struct { conf *config.OpsGenieConfig tmpl *template.Template - logger log.Logger + logger *slog.Logger client *http.Client retrier *notify.Retrier } // New returns a new OpsGenie notifier. -func New(c *config.OpsGenieConfig, t *template.Template, l log.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { +func New(c *config.OpsGenieConfig, t *template.Template, l *slog.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { client, err := commoncfg.NewClientFromConfig(*c.HTTPConfig, "opsgenie", httpOpts...) if err != nil { return nil, err @@ -135,7 +134,7 @@ func (n *Notifier) createRequests(ctx context.Context, as ...*types.Alert) ([]*h } data := notify.GetTemplateData(ctx, n.tmpl, as, n.logger) - level.Debug(n.logger).Log("alert", key) + n.logger.Debug("extracted group key", "key", key) tmpl := notify.TmplText(n.tmpl, data, &err) @@ -175,7 +174,7 @@ func (n *Notifier) createRequests(ctx context.Context, as ...*types.Alert) ([]*h default: message, truncated := notify.TruncateInRunes(tmpl(n.conf.Message), maxMessageLenRunes) if truncated { - level.Warn(n.logger).Log("msg", "Truncated message", "alert", key, "max_runes", maxMessageLenRunes) + n.logger.Warn("Truncated message", "alert", key, "max_runes", maxMessageLenRunes) } createEndpointURL := n.conf.APIURL.Copy() diff --git a/vendor/github.com/prometheus/alertmanager/notify/pagerduty/pagerduty.go b/vendor/github.com/prometheus/alertmanager/notify/pagerduty/pagerduty.go index 6f6e1a20a8..abab5a70be 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/pagerduty/pagerduty.go +++ b/vendor/github.com/prometheus/alertmanager/notify/pagerduty/pagerduty.go @@ -20,13 +20,12 @@ import ( "errors" "fmt" "io" + "log/slog" "net/http" "os" "strings" "github.com/alecthomas/units" - "github.com/go-kit/log" - "github.com/go-kit/log/level" commoncfg "github.com/prometheus/common/config" "github.com/prometheus/common/model" @@ -48,14 +47,14 @@ const ( type Notifier struct { conf *config.PagerdutyConfig tmpl *template.Template - logger log.Logger + logger *slog.Logger apiV1 string // for tests. client *http.Client retrier *notify.Retrier } // New returns a new PagerDuty notifier. -func New(c *config.PagerdutyConfig, t *template.Template, l log.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { +func New(c *config.PagerdutyConfig, t *template.Template, l *slog.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { client, err := commoncfg.NewClientFromConfig(*c.HTTPConfig, "pagerduty", httpOpts...) if err != nil { return nil, err @@ -133,7 +132,7 @@ func (n *Notifier) encodeMessage(msg *pagerDutyMessage) (bytes.Buffer, error) { } warningMsg := fmt.Sprintf("Truncated Details because message of size %s exceeds limit %s", units.MetricBytes(buf.Len()).String(), units.MetricBytes(maxEventSize).String()) - level.Warn(n.logger).Log("msg", warningMsg) + n.logger.Warn(warningMsg) buf.Reset() if err := json.NewEncoder(&buf).Encode(msg); err != nil { @@ -157,7 +156,7 @@ func (n *Notifier) notifyV1( description, truncated := notify.TruncateInRunes(tmpl(n.conf.Description), maxV1DescriptionLenRunes) if truncated { - level.Warn(n.logger).Log("msg", "Truncated description", "key", key, "max_runes", maxV1DescriptionLenRunes) + n.logger.Warn("Truncated description", "key", key, "max_runes", maxV1DescriptionLenRunes) } serviceKey := string(n.conf.ServiceKey) @@ -222,7 +221,7 @@ func (n *Notifier) notifyV2( summary, truncated := notify.TruncateInRunes(tmpl(n.conf.Description), maxV2SummaryLenRunes) if truncated { - level.Warn(n.logger).Log("msg", "Truncated summary", "key", key, "max_runes", maxV2SummaryLenRunes) + n.logger.Warn("Truncated summary", "key", key, "max_runes", maxV2SummaryLenRunes) } routingKey := string(n.conf.RoutingKey) @@ -319,7 +318,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) eventType = pagerDutyEventResolve } - level.Debug(n.logger).Log("incident", key, "eventType", eventType) + n.logger.Debug("extracted group key", "key", key, "eventType", eventType) details := make(map[string]string, len(n.conf.Details)) for k, v := range n.conf.Details { diff --git a/vendor/github.com/prometheus/alertmanager/notify/pushover/pushover.go b/vendor/github.com/prometheus/alertmanager/notify/pushover/pushover.go index a8f4644f65..5445b977cb 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/pushover/pushover.go +++ b/vendor/github.com/prometheus/alertmanager/notify/pushover/pushover.go @@ -16,14 +16,13 @@ package pushover import ( "context" "fmt" + "log/slog" "net/http" "net/url" "os" "strings" "time" - "github.com/go-kit/log" - "github.com/go-kit/log/level" commoncfg "github.com/prometheus/common/config" "github.com/prometheus/alertmanager/config" @@ -45,14 +44,14 @@ const ( type Notifier struct { conf *config.PushoverConfig tmpl *template.Template - logger log.Logger + logger *slog.Logger client *http.Client retrier *notify.Retrier apiURL string // for tests. } // New returns a new Pushover notifier. -func New(c *config.PushoverConfig, t *template.Template, l log.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { +func New(c *config.PushoverConfig, t *template.Template, l *slog.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { client, err := commoncfg.NewClientFromConfig(*c.HTTPConfig, "pushover", httpOpts...) if err != nil { return nil, err @@ -75,7 +74,8 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) } data := notify.GetTemplateData(ctx, n.tmpl, as, n.logger) - level.Debug(n.logger).Log("incident", key) + // @tjhop: should this use `group` for the keyval like most other notify implementations? + n.logger.Debug("extracted group key", "incident", key) var ( err error @@ -113,7 +113,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) title, truncated := notify.TruncateInRunes(tmpl(n.conf.Title), maxTitleLenRunes) if truncated { - level.Warn(n.logger).Log("msg", "Truncated title", "incident", key, "max_runes", maxTitleLenRunes) + n.logger.Warn("Truncated title", "incident", key, "max_runes", maxTitleLenRunes) } parameters.Add("title", title) @@ -126,7 +126,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) message, truncated = notify.TruncateInRunes(message, maxMessageLenRunes) if truncated { - level.Warn(n.logger).Log("msg", "Truncated message", "incident", key, "max_runes", maxMessageLenRunes) + n.logger.Warn("Truncated message", "incident", key, "max_runes", maxMessageLenRunes) } message = strings.TrimSpace(message) if message == "" { @@ -137,7 +137,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) supplementaryURL, truncated := notify.TruncateInRunes(tmpl(n.conf.URL), maxURLLenRunes) if truncated { - level.Warn(n.logger).Log("msg", "Truncated URL", "incident", key, "max_runes", maxURLLenRunes) + n.logger.Warn("Truncated URL", "incident", key, "max_runes", maxURLLenRunes) } parameters.Add("url", supplementaryURL) parameters.Add("url_title", tmpl(n.conf.URLTitle)) @@ -163,7 +163,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) } u.RawQuery = parameters.Encode() // Don't log the URL as it contains secret data (see #1825). - level.Debug(n.logger).Log("msg", "Sending message", "incident", key) + n.logger.Debug("Sending message", "incident", key) resp, err := notify.PostText(ctx, n.client, u.String(), nil) if err != nil { return true, notify.RedactURL(err) diff --git a/vendor/github.com/prometheus/alertmanager/notify/slack/slack.go b/vendor/github.com/prometheus/alertmanager/notify/slack/slack.go index b4b5a195e9..c335ab5f00 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/slack/slack.go +++ b/vendor/github.com/prometheus/alertmanager/notify/slack/slack.go @@ -19,12 +19,11 @@ import ( "encoding/json" "fmt" "io" + "log/slog" "net/http" "os" "strings" - "github.com/go-kit/log" - "github.com/go-kit/log/level" commoncfg "github.com/prometheus/common/config" "github.com/prometheus/alertmanager/config" @@ -40,7 +39,7 @@ const maxTitleLenRunes = 1024 type Notifier struct { conf *config.SlackConfig tmpl *template.Template - logger log.Logger + logger *slog.Logger client *http.Client retrier *notify.Retrier @@ -48,7 +47,7 @@ type Notifier struct { } // New returns a new Slack notification handler. -func New(c *config.SlackConfig, t *template.Template, l log.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { +func New(c *config.SlackConfig, t *template.Template, l *slog.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { client, err := commoncfg.NewClientFromConfig(*c.HTTPConfig, "slack", httpOpts...) if err != nil { return nil, err @@ -112,7 +111,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) if err != nil { return false, err } - level.Warn(n.logger).Log("msg", "Truncated title", "key", key, "max_runes", maxTitleLenRunes) + n.logger.Warn("Truncated title", "key", key, "max_runes", maxTitleLenRunes) } att := &attachment{ Title: title, diff --git a/vendor/github.com/prometheus/alertmanager/notify/sns/sns.go b/vendor/github.com/prometheus/alertmanager/notify/sns/sns.go index 996566c726..3b6026e546 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/sns/sns.go +++ b/vendor/github.com/prometheus/alertmanager/notify/sns/sns.go @@ -17,6 +17,7 @@ import ( "context" "errors" "fmt" + "log/slog" "net/http" "strings" "unicode/utf8" @@ -27,8 +28,6 @@ import ( "github.com/aws/aws-sdk-go/aws/credentials/stscreds" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/sns" - "github.com/go-kit/log" - "github.com/go-kit/log/level" commoncfg "github.com/prometheus/common/config" "github.com/prometheus/alertmanager/config" @@ -41,13 +40,13 @@ import ( type Notifier struct { conf *config.SNSConfig tmpl *template.Template - logger log.Logger + logger *slog.Logger client *http.Client retrier *notify.Retrier } // New returns a new SNS notification handler. -func New(c *config.SNSConfig, t *template.Template, l log.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { +func New(c *config.SNSConfig, t *template.Template, l *slog.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { client, err := commoncfg.NewClientFromConfig(*c.HTTPConfig, "sns", httpOpts...) if err != nil { return nil, err @@ -63,12 +62,12 @@ func New(c *config.SNSConfig, t *template.Template, l log.Logger, httpOpts ...co func (n *Notifier) Notify(ctx context.Context, alert ...*types.Alert) (bool, error) { var ( - err error - data = notify.GetTemplateData(ctx, n.tmpl, alert, n.logger) - tmpl = notify.TmplText(n.tmpl, data, &err) + tmplErr error + data = notify.GetTemplateData(ctx, n.tmpl, alert, n.logger) + tmpl = notify.TmplText(n.tmpl, data, &tmplErr) ) - client, err := n.createSNSClient(tmpl) + client, err := n.createSNSClient(tmpl, &tmplErr) if err != nil { var e awserr.RequestFailure if errors.As(err, &e) { @@ -77,7 +76,7 @@ func (n *Notifier) Notify(ctx context.Context, alert ...*types.Alert) (bool, err return true, err } - publishInput, err := n.createPublishInput(ctx, tmpl) + publishInput, err := n.createPublishInput(ctx, tmpl, &tmplErr) if err != nil { return true, err } @@ -94,12 +93,12 @@ func (n *Notifier) Notify(ctx context.Context, alert ...*types.Alert) (bool, err return true, err } - level.Debug(n.logger).Log("msg", "SNS message successfully published", "message_id", publishOutput.MessageId, "sequence number", publishOutput.SequenceNumber) + n.logger.Debug("SNS message successfully published", "message_id", publishOutput.MessageId, "sequence number", publishOutput.SequenceNumber) return false, nil } -func (n *Notifier) createSNSClient(tmpl func(string) string) (*sns.SNS, error) { +func (n *Notifier) createSNSClient(tmpl func(string) string, tmplErr *error) (*sns.SNS, error) { var creds *credentials.Credentials // If there are provided sigV4 credentials we want to use those to create a session. if n.conf.Sigv4.AccessKey != "" && n.conf.Sigv4.SecretKey != "" { @@ -115,6 +114,9 @@ func (n *Notifier) createSNSClient(tmpl func(string) string) (*sns.SNS, error) { if err != nil { return nil, err } + if *tmplErr != nil { + return nil, notify.NewErrorWithReason(notify.ClientErrorReason, fmt.Errorf("execute 'api_url' template: %w", *tmplErr)) + } if n.conf.Sigv4.RoleARN != "" { var stsSess *session.Session @@ -144,13 +146,19 @@ func (n *Notifier) createSNSClient(tmpl func(string) string) (*sns.SNS, error) { return client, nil } -func (n *Notifier) createPublishInput(ctx context.Context, tmpl func(string) string) (*sns.PublishInput, error) { +func (n *Notifier) createPublishInput(ctx context.Context, tmpl func(string) string, tmplErr *error) (*sns.PublishInput, error) { publishInput := &sns.PublishInput{} messageAttributes := n.createMessageAttributes(tmpl) + if *tmplErr != nil { + return nil, notify.NewErrorWithReason(notify.ClientErrorReason, fmt.Errorf("execute 'attributes' template: %w", *tmplErr)) + } // Max message size for a message in a SNS publish request is 256KB, except for SMS messages where the limit is 1600 characters/runes. messageSizeLimit := 256 * 1024 if n.conf.TopicARN != "" { topicARN := tmpl(n.conf.TopicARN) + if *tmplErr != nil { + return nil, notify.NewErrorWithReason(notify.ClientErrorReason, fmt.Errorf("execute 'topic_arn' template: %w", *tmplErr)) + } publishInput.SetTopicArn(topicARN) // If we are using a topic ARN, it could be a FIFO topic specified by the topic's suffix ".fifo". if strings.HasSuffix(topicARN, ".fifo") { @@ -165,14 +173,24 @@ func (n *Notifier) createPublishInput(ctx context.Context, tmpl func(string) str } if n.conf.PhoneNumber != "" { publishInput.SetPhoneNumber(tmpl(n.conf.PhoneNumber)) + if *tmplErr != nil { + return nil, notify.NewErrorWithReason(notify.ClientErrorReason, fmt.Errorf("execute 'phone_number' template: %w", *tmplErr)) + } // If we have an SMS message, we need to truncate to 1600 characters/runes. messageSizeLimit = 1600 } if n.conf.TargetARN != "" { publishInput.SetTargetArn(tmpl(n.conf.TargetARN)) + if *tmplErr != nil { + return nil, notify.NewErrorWithReason(notify.ClientErrorReason, fmt.Errorf("execute 'target_arn' template: %w", *tmplErr)) + } } - messageToSend, isTrunc, err := validateAndTruncateMessage(tmpl(n.conf.Message), messageSizeLimit) + tmplMessage := tmpl(n.conf.Message) + if *tmplErr != nil { + return nil, notify.NewErrorWithReason(notify.ClientErrorReason, fmt.Errorf("execute 'message' template: %w", *tmplErr)) + } + messageToSend, isTrunc, err := validateAndTruncateMessage(tmplMessage, messageSizeLimit) if err != nil { return nil, err } @@ -186,6 +204,9 @@ func (n *Notifier) createPublishInput(ctx context.Context, tmpl func(string) str if n.conf.Subject != "" { publishInput.SetSubject(tmpl(n.conf.Subject)) + if *tmplErr != nil { + return nil, notify.NewErrorWithReason(notify.ClientErrorReason, fmt.Errorf("execute 'subject' template: %w", *tmplErr)) + } } return publishInput, nil diff --git a/vendor/github.com/prometheus/alertmanager/notify/telegram/telegram.go b/vendor/github.com/prometheus/alertmanager/notify/telegram/telegram.go index 3e60ab7641..3bd359cc7a 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/telegram/telegram.go +++ b/vendor/github.com/prometheus/alertmanager/notify/telegram/telegram.go @@ -16,12 +16,11 @@ package telegram import ( "context" "fmt" + "log/slog" "net/http" "os" "strings" - "github.com/go-kit/log" - "github.com/go-kit/log/level" commoncfg "github.com/prometheus/common/config" "gopkg.in/telebot.v3" @@ -38,13 +37,13 @@ const maxMessageLenRunes = 4096 type Notifier struct { conf *config.TelegramConfig tmpl *template.Template - logger log.Logger + logger *slog.Logger client *telebot.Bot retrier *notify.Retrier } // New returns a new Telegram notification handler. -func New(conf *config.TelegramConfig, t *template.Template, l log.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { +func New(conf *config.TelegramConfig, t *template.Template, l *slog.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { httpclient, err := commoncfg.NewClientFromConfig(*conf.HTTPConfig, "telegram", httpOpts...) if err != nil { return nil, err @@ -82,7 +81,7 @@ func (n *Notifier) Notify(ctx context.Context, alert ...*types.Alert) (bool, err messageText, truncated := notify.TruncateInRunes(tmpl(n.conf.Message), maxMessageLenRunes) if truncated { - level.Warn(n.logger).Log("msg", "Truncated message", "alert", key, "max_runes", maxMessageLenRunes) + n.logger.Warn("Truncated message", "alert", key, "max_runes", maxMessageLenRunes) } n.client.Token, err = n.getBotToken() @@ -93,11 +92,13 @@ func (n *Notifier) Notify(ctx context.Context, alert ...*types.Alert) (bool, err message, err := n.client.Send(telebot.ChatID(n.conf.ChatID), messageText, &telebot.SendOptions{ DisableNotification: n.conf.DisableNotifications, DisableWebPagePreview: true, + ThreadID: n.conf.MessageThreadID, + ParseMode: n.conf.ParseMode, }) if err != nil { return true, err } - level.Debug(n.logger).Log("msg", "Telegram message successfully published", "message_id", message.ID, "chat_id", message.Chat.ID) + n.logger.Debug("Telegram message successfully published", "message_id", message.ID, "chat_id", message.Chat.ID) return false, nil } diff --git a/vendor/github.com/prometheus/alertmanager/notify/util.go b/vendor/github.com/prometheus/alertmanager/notify/util.go index bd54e2b47d..14e3050bdb 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/util.go +++ b/vendor/github.com/prometheus/alertmanager/notify/util.go @@ -19,12 +19,11 @@ import ( "errors" "fmt" "io" + "log/slog" "net/http" "net/url" "strings" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/prometheus/common/version" "github.com/prometheus/alertmanager/template" @@ -34,7 +33,7 @@ import ( // truncationMarker is the character used to represent a truncation. const truncationMarker = "…" -// UserAgentHeader is the default User-Agent for notification requests +// UserAgentHeader is the default User-Agent for notification requests. var UserAgentHeader = fmt.Sprintf("Alertmanager/%s", version.Version) // RedactURL removes the URL part from an error of *url.Error type. @@ -47,7 +46,7 @@ func RedactURL(err error) error { return e } -// Get sends a GET request to the given URL +// Get sends a GET request to the given URL. func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) { return request(ctx, client, http.MethodGet, url, "", nil) } @@ -180,14 +179,14 @@ func (k Key) String() string { } // GetTemplateData creates the template data from the context and the alerts. -func GetTemplateData(ctx context.Context, tmpl *template.Template, alerts []*types.Alert, l log.Logger) *template.Data { +func GetTemplateData(ctx context.Context, tmpl *template.Template, alerts []*types.Alert, l *slog.Logger) *template.Data { recv, ok := ReceiverName(ctx) if !ok { - level.Error(l).Log("msg", "Missing receiver") + l.Error("Missing receiver") } groupLabels, ok := GroupLabels(ctx) if !ok { - level.Error(l).Log("msg", "Missing group labels") + l.Error("Missing group labels") } return tmpl.Data(recv, groupLabels, alerts...) } diff --git a/vendor/github.com/prometheus/alertmanager/notify/victorops/victorops.go b/vendor/github.com/prometheus/alertmanager/notify/victorops/victorops.go index 44088b4eb3..ac89222ece 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/victorops/victorops.go +++ b/vendor/github.com/prometheus/alertmanager/notify/victorops/victorops.go @@ -18,12 +18,11 @@ import ( "context" "encoding/json" "fmt" + "log/slog" "net/http" "os" "strings" - "github.com/go-kit/log" - "github.com/go-kit/log/level" commoncfg "github.com/prometheus/common/config" "github.com/prometheus/common/model" @@ -40,13 +39,13 @@ const maxMessageLenRunes = 20480 type Notifier struct { conf *config.VictorOpsConfig tmpl *template.Template - logger log.Logger + logger *slog.Logger client *http.Client retrier *notify.Retrier } // New returns a new VictorOps notifier. -func New(c *config.VictorOpsConfig, t *template.Template, l log.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { +func New(c *config.VictorOpsConfig, t *template.Template, l *slog.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { client, err := commoncfg.NewClientFromConfig(*c.HTTPConfig, "victorops", httpOpts...) if err != nil { return nil, err @@ -142,7 +141,7 @@ func (n *Notifier) createVictorOpsPayload(ctx context.Context, as ...*types.Aler stateMessage, truncated := notify.TruncateInRunes(stateMessage, maxMessageLenRunes) if truncated { - level.Warn(n.logger).Log("msg", "Truncated state_message", "incident", key, "max_runes", maxMessageLenRunes) + n.logger.Warn("Truncated state_message", "incident", key, "max_runes", maxMessageLenRunes) } msg := map[string]string{ diff --git a/vendor/github.com/prometheus/alertmanager/notify/webex/webex.go b/vendor/github.com/prometheus/alertmanager/notify/webex/webex.go index 9e95e3ed9b..8ec916dfb6 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/webex/webex.go +++ b/vendor/github.com/prometheus/alertmanager/notify/webex/webex.go @@ -17,10 +17,9 @@ import ( "bytes" "context" "encoding/json" + "log/slog" "net/http" - "github.com/go-kit/log" - "github.com/go-kit/log/level" commoncfg "github.com/prometheus/common/config" "github.com/prometheus/alertmanager/config" @@ -30,6 +29,7 @@ import ( ) const ( + // nolint:godot // maxMessageSize represents the maximum message length that Webex supports. maxMessageSize = 7439 ) @@ -37,13 +37,13 @@ const ( type Notifier struct { conf *config.WebexConfig tmpl *template.Template - logger log.Logger + logger *slog.Logger client *http.Client retrier *notify.Retrier } // New returns a new Webex notifier. -func New(c *config.WebexConfig, t *template.Template, l log.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { +func New(c *config.WebexConfig, t *template.Template, l *slog.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { client, err := commoncfg.NewClientFromConfig(*c.HTTPConfig, "webex", httpOpts...) if err != nil { return nil, err @@ -72,7 +72,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) return false, err } - level.Debug(n.logger).Log("incident", key) + n.logger.Debug("extracted group key", "key", key) data := notify.GetTemplateData(ctx, n.tmpl, as, n.logger) tmpl := notify.TmplText(n.tmpl, data, &err) @@ -87,12 +87,12 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) message, truncated := notify.TruncateInBytes(message, maxMessageSize) if truncated { - level.Debug(n.logger).Log("msg", "message truncated due to exceeding maximum allowed length by webex", "truncated_message", message) + n.logger.Debug("message truncated due to exceeding maximum allowed length by webex", "truncated_message", message) } w := webhook{ Markdown: message, - RoomID: n.conf.RoomID, + RoomID: tmpl(n.conf.RoomID), } var payload bytes.Buffer diff --git a/vendor/github.com/prometheus/alertmanager/notify/webhook/webhook.go b/vendor/github.com/prometheus/alertmanager/notify/webhook/webhook.go index 41241569ef..41b9f497dc 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/webhook/webhook.go +++ b/vendor/github.com/prometheus/alertmanager/notify/webhook/webhook.go @@ -18,13 +18,11 @@ import ( "context" "encoding/json" "fmt" - "io" + "log/slog" "net/http" "os" "strings" - "github.com/go-kit/log" - "github.com/go-kit/log/level" commoncfg "github.com/prometheus/common/config" "github.com/prometheus/alertmanager/config" @@ -37,13 +35,13 @@ import ( type Notifier struct { conf *config.WebhookConfig tmpl *template.Template - logger log.Logger + logger *slog.Logger client *http.Client retrier *notify.Retrier } // New returns a new Webhook. -func New(conf *config.WebhookConfig, t *template.Template, l log.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { +func New(conf *config.WebhookConfig, t *template.Template, l *slog.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { client, err := commoncfg.NewClientFromConfig(*conf.HTTPConfig, "webhook", httpOpts...) if err != nil { return nil, err @@ -55,11 +53,7 @@ func New(conf *config.WebhookConfig, t *template.Template, l log.Logger, httpOpt client: client, // Webhooks are assumed to respond with 2xx response codes on a successful // request and 5xx response codes are assumed to be recoverable. - retrier: ¬ify.Retrier{ - CustomDetailsFunc: func(_ int, body io.Reader) string { - return errDetails(body, conf.URL.String()) - }, - }, + retrier: ¬ify.Retrier{}, }, nil } @@ -88,9 +82,13 @@ func (n *Notifier) Notify(ctx context.Context, alerts ...*types.Alert) (bool, er groupKey, err := notify.ExtractGroupKey(ctx) if err != nil { - level.Error(n.logger).Log("err", err) + // @tjhop: should we `return false, err` here as we do in most + // other Notify() implementations? + n.logger.Error("error extracting group key", "err", err) } + // @tjhop: should we debug log the key here like most other Notify() implementations? + msg := &Message{ Version: "4", Data: data, @@ -114,8 +112,17 @@ func (n *Notifier) Notify(ctx context.Context, alerts ...*types.Alert) (bool, er url = strings.TrimSpace(string(content)) } + if n.conf.Timeout > 0 { + postCtx, cancel := context.WithTimeoutCause(ctx, n.conf.Timeout, fmt.Errorf("configured webhook timeout reached (%s)", n.conf.Timeout)) + defer cancel() + ctx = postCtx + } + resp, err := notify.PostJSON(ctx, n.client, url, &buf) if err != nil { + if ctx.Err() != nil { + err = fmt.Errorf("%w: %w", err, context.Cause(ctx)) + } return true, notify.RedactURL(err) } defer notify.Drain(resp) @@ -126,14 +133,3 @@ func (n *Notifier) Notify(ctx context.Context, alerts ...*types.Alert) (bool, er } return shouldRetry, err } - -func errDetails(body io.Reader, url string) string { - if body == nil { - return url - } - bs, err := io.ReadAll(body) - if err != nil { - return url - } - return fmt.Sprintf("%s: %s", url, string(bs)) -} diff --git a/vendor/github.com/prometheus/alertmanager/notify/wechat/wechat.go b/vendor/github.com/prometheus/alertmanager/notify/wechat/wechat.go index 9eb77b66a5..4aab58ca30 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/wechat/wechat.go +++ b/vendor/github.com/prometheus/alertmanager/notify/wechat/wechat.go @@ -20,12 +20,11 @@ import ( "errors" "fmt" "io" + "log/slog" "net/http" "net/url" "time" - "github.com/go-kit/log" - "github.com/go-kit/log/level" commoncfg "github.com/prometheus/common/config" "github.com/prometheus/alertmanager/config" @@ -38,7 +37,7 @@ import ( type Notifier struct { conf *config.WechatConfig tmpl *template.Template - logger log.Logger + logger *slog.Logger client *http.Client accessToken string @@ -71,7 +70,7 @@ type weChatResponse struct { } // New returns a new Wechat notifier. -func New(c *config.WechatConfig, t *template.Template, l log.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { +func New(c *config.WechatConfig, t *template.Template, l *slog.Logger, httpOpts ...commoncfg.HTTPClientOption) (*Notifier, error) { client, err := commoncfg.NewClientFromConfig(*c.HTTPConfig, "wechat", httpOpts...) if err != nil { return nil, err @@ -87,7 +86,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) return false, err } - level.Debug(n.logger).Log("incident", key) + n.logger.Debug("extracted group key", "key", key) data := notify.GetTemplateData(ctx, n.tmpl, as, n.logger) tmpl := notify.TmplText(n.tmpl, data, &err) @@ -175,7 +174,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) if err != nil { return true, err } - level.Debug(n.logger).Log("response", string(body), "incident", key) + n.logger.Debug(string(body), "incident", key) var weResp weChatResponse if err := json.Unmarshal(body, &weResp); err != nil { diff --git a/vendor/github.com/prometheus/alertmanager/pkg/labels/matcher.go b/vendor/github.com/prometheus/alertmanager/pkg/labels/matcher.go index f37fcb2173..eba6b4ca60 100644 --- a/vendor/github.com/prometheus/alertmanager/pkg/labels/matcher.go +++ b/vendor/github.com/prometheus/alertmanager/pkg/labels/matcher.go @@ -205,7 +205,7 @@ func (ms Matchers) String() string { return buf.String() } -// This is copied from matchers/parse/lexer.go. It will be removed when +// This is copied from matcher/parse/lexer.go. It will be removed when // the transition window from classic matchers to UTF-8 matchers is complete, // as then we can use double quotes when printing the label name for all // matchers. Until then, the classic parser does not understand double quotes diff --git a/vendor/github.com/prometheus/alertmanager/pkg/labels/parse.go b/vendor/github.com/prometheus/alertmanager/pkg/labels/parse.go index 5138716e0a..f84b29e84b 100644 --- a/vendor/github.com/prometheus/alertmanager/pkg/labels/parse.go +++ b/vendor/github.com/prometheus/alertmanager/pkg/labels/parse.go @@ -136,7 +136,7 @@ func ParseMatcher(s string) (_ *Matcher, err error) { return nil, fmt.Errorf("matcher value not valid UTF-8: %s", ms[3]) } - // Unescape the rawValue: + // Unescape the rawValue. for i, r := range rawValue { if escaped { escaped = false diff --git a/vendor/github.com/prometheus/alertmanager/provider/mem/mem.go b/vendor/github.com/prometheus/alertmanager/provider/mem/mem.go index 0e39ba1d5f..3948697d84 100644 --- a/vendor/github.com/prometheus/alertmanager/provider/mem/mem.go +++ b/vendor/github.com/prometheus/alertmanager/provider/mem/mem.go @@ -15,11 +15,10 @@ package mem import ( "context" + "log/slog" "sync" "time" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/model" @@ -34,16 +33,17 @@ const alertChannelLength = 200 type Alerts struct { cancel context.CancelFunc + mtx sync.Mutex + alerts *store.Alerts - marker types.Marker + marker types.AlertMarker - mtx sync.Mutex listeners map[int]listeningAlerts next int callback AlertStoreCallback - logger log.Logger + logger *slog.Logger } type AlertStoreCallback interface { @@ -85,7 +85,7 @@ func (a *Alerts) registerMetrics(r prometheus.Registerer) { } // NewAlerts returns a new alert provider. -func NewAlerts(ctx context.Context, m types.Marker, intervalGC time.Duration, alertCallback AlertStoreCallback, l log.Logger, r prometheus.Registerer) (*Alerts, error) { +func NewAlerts(ctx context.Context, m types.AlertMarker, intervalGC time.Duration, alertCallback AlertStoreCallback, l *slog.Logger, r prometheus.Registerer) (*Alerts, error) { if alertCallback == nil { alertCallback = noopCallback{} } @@ -97,40 +97,56 @@ func NewAlerts(ctx context.Context, m types.Marker, intervalGC time.Duration, al cancel: cancel, listeners: map[int]listeningAlerts{}, next: 0, - logger: log.With(l, "component", "provider"), + logger: l.With("component", "provider"), callback: alertCallback, } - a.alerts.SetGCCallback(func(alerts []*types.Alert) { - for _, alert := range alerts { - // As we don't persist alerts, we no longer consider them after - // they are resolved. Alerts waiting for resolved notifications are - // held in memory in aggregation groups redundantly. - m.Delete(alert.Fingerprint()) - a.callback.PostDelete(alert) - } - - a.mtx.Lock() - for i, l := range a.listeners { - select { - case <-l.done: - delete(a.listeners, i) - close(l.alerts) - default: - // listener is not closed yet, hence proceed. - } - } - a.mtx.Unlock() - }) if r != nil { a.registerMetrics(r) } - go a.alerts.Run(ctx, intervalGC) + go a.gcLoop(ctx, intervalGC) return a, nil } +func (a *Alerts) gcLoop(ctx context.Context, interval time.Duration) { + t := time.NewTicker(interval) + defer t.Stop() + for { + select { + case <-ctx.Done(): + return + case <-t.C: + a.gc() + } + } +} + +func (a *Alerts) gc() { + a.mtx.Lock() + defer a.mtx.Unlock() + + deleted := a.alerts.GC() + for _, alert := range deleted { + // As we don't persist alerts, we no longer consider them after + // they are resolved. Alerts waiting for resolved notifications are + // held in memory in aggregation groups redundantly. + a.marker.Delete(alert.Fingerprint()) + a.callback.PostDelete(&alert) + } + + for i, l := range a.listeners { + select { + case <-l.done: + delete(a.listeners, i) + close(l.alerts) + default: + // listener is not closed yet, hence proceed. + } + } +} + // Close the alert provider. func (a *Alerts) Close() { if a.cancel != nil { @@ -151,7 +167,6 @@ func max(a, b int) int { func (a *Alerts) Subscribe() provider.AlertIterator { a.mtx.Lock() defer a.mtx.Unlock() - var ( done = make(chan struct{}) alerts = a.alerts.List() @@ -175,11 +190,13 @@ func (a *Alerts) GetPending() provider.AlertIterator { ch = make(chan *types.Alert, alertChannelLength) done = make(chan struct{}) ) + a.mtx.Lock() + defer a.mtx.Unlock() + alerts := a.alerts.List() go func() { defer close(ch) - - for _, a := range a.alerts.List() { + for _, a := range alerts { select { case ch <- a: case <-done: @@ -193,11 +210,16 @@ func (a *Alerts) GetPending() provider.AlertIterator { // Get returns the alert for a given fingerprint. func (a *Alerts) Get(fp model.Fingerprint) (*types.Alert, error) { + a.mtx.Lock() + defer a.mtx.Unlock() return a.alerts.Get(fp) } // Put adds the given alert to the set. func (a *Alerts) Put(alerts ...*types.Alert) error { + a.mtx.Lock() + defer a.mtx.Unlock() + for _, alert := range alerts { fp := alert.Fingerprint() @@ -216,25 +238,23 @@ func (a *Alerts) Put(alerts ...*types.Alert) error { } if err := a.callback.PreStore(alert, existing); err != nil { - level.Error(a.logger).Log("msg", "pre-store callback returned error on set alert", "err", err) + a.logger.Error("pre-store callback returned error on set alert", "err", err) continue } if err := a.alerts.Set(alert); err != nil { - level.Error(a.logger).Log("msg", "error on set alert", "err", err) + a.logger.Error("error on set alert", "err", err) continue } a.callback.PostStore(alert, existing) - a.mtx.Lock() for _, l := range a.listeners { select { case l.alerts <- alert: case <-l.done: } } - a.mtx.Unlock() } return nil @@ -242,6 +262,9 @@ func (a *Alerts) Put(alerts ...*types.Alert) error { // count returns the number of non-resolved alerts we currently have stored filtered by the provided state. func (a *Alerts) count(state types.AlertState) int { + a.mtx.Lock() + defer a.mtx.Unlock() + var count int for _, alert := range a.alerts.List() { if alert.Resolved() { diff --git a/vendor/github.com/prometheus/alertmanager/provider/provider.go b/vendor/github.com/prometheus/alertmanager/provider/provider.go index 5fcce20360..4d1f76f206 100644 --- a/vendor/github.com/prometheus/alertmanager/provider/provider.go +++ b/vendor/github.com/prometheus/alertmanager/provider/provider.go @@ -47,7 +47,7 @@ type AlertIterator interface { Next() <-chan *types.Alert } -// NewAlertIterator returns a new AlertIterator based on the generic alertIterator type +// NewAlertIterator returns a new AlertIterator based on the generic alertIterator type. func NewAlertIterator(ch <-chan *types.Alert, done chan struct{}, err error) AlertIterator { return &alertIterator{ ch: ch, diff --git a/vendor/github.com/prometheus/alertmanager/silence/silence.go b/vendor/github.com/prometheus/alertmanager/silence/silence.go index 710323f747..7e25dc3b7b 100644 --- a/vendor/github.com/prometheus/alertmanager/silence/silence.go +++ b/vendor/github.com/prometheus/alertmanager/silence/silence.go @@ -20,6 +20,7 @@ import ( "errors" "fmt" "io" + "log/slog" "math/rand" "os" "reflect" @@ -28,34 +29,33 @@ import ( "sync" "time" - "github.com/benbjohnson/clock" - "github.com/go-kit/log" - "github.com/go-kit/log/level" + "github.com/coder/quartz" uuid "github.com/gofrs/uuid" "github.com/matttproud/golang_protobuf_extensions/pbutil" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/model" + "github.com/prometheus/common/promslog" "github.com/prometheus/alertmanager/cluster" - "github.com/prometheus/alertmanager/matchers/compat" + "github.com/prometheus/alertmanager/matcher/compat" "github.com/prometheus/alertmanager/pkg/labels" pb "github.com/prometheus/alertmanager/silence/silencepb" "github.com/prometheus/alertmanager/types" ) // ErrNotFound is returned if a silence was not found. -var ErrNotFound = fmt.Errorf("silence not found") +var ErrNotFound = errors.New("silence not found") // ErrInvalidState is returned if the state isn't valid. -var ErrInvalidState = fmt.Errorf("invalid state") +var ErrInvalidState = errors.New("invalid state") -type matcherCache map[*pb.Silence]labels.Matchers +type matcherCache map[string]labels.Matchers // Get retrieves the matchers for a given silence. If it is a missed cache // access, it compiles and adds the matchers of the requested silence to the // cache. func (c matcherCache) Get(s *pb.Silence) (labels.Matchers, error) { - if m, ok := c[s]; ok { + if m, ok := c[s.Id]; ok { return m, nil } return c.add(s) @@ -88,20 +88,20 @@ func (c matcherCache) add(s *pb.Silence) (labels.Matchers, error) { ms[i] = matcher } - c[s] = ms + c[s.Id] = ms return ms, nil } -// Silencer binds together a Marker and a Silences to implement the Muter +// Silencer binds together a AlertMarker and a Silences to implement the Muter // interface. type Silencer struct { silences *Silences - marker types.Marker - logger log.Logger + marker types.AlertMarker + logger *slog.Logger } // NewSilencer returns a new Silencer. -func NewSilencer(s *Silences, m types.Marker, l log.Logger) *Silencer { +func NewSilencer(s *Silences, m types.AlertMarker, l *slog.Logger) *Silencer { return &Silencer{ silences: s, marker: m, @@ -148,7 +148,7 @@ func (s *Silencer) Mutes(lset model.LabelSet) bool { ) } if err != nil { - level.Error(s.logger).Log("msg", "Querying silences failed, alerts might not get silenced correctly", "err", err) + s.logger.Error("Querying silences failed, alerts might not get silenced correctly", "err", err) } if len(allSils) == 0 { // Easy case, neither active nor pending silences anymore. @@ -171,8 +171,8 @@ func (s *Silencer) Mutes(lset model.LabelSet) bool { // Do nothing, silence has expired in the meantime. } } - level.Debug(s.logger).Log( - "msg", "determined current silences state", + s.logger.Debug( + "determined current silences state", "now", now, "total", len(allSils), "active", len(activeIDs), @@ -188,11 +188,12 @@ func (s *Silencer) Mutes(lset model.LabelSet) bool { // Silences holds a silence state that can be modified, queried, and snapshot. type Silences struct { - clock clock.Clock + clock quartz.Clock - logger log.Logger + logger *slog.Logger metrics *metrics retention time.Duration + limits Limits mtx sync.RWMutex st state @@ -201,6 +202,16 @@ type Silences struct { mc matcherCache } +// Limits contains the limits for silences. +type Limits struct { + // MaxSilences limits the maximum number of silences, including expired + // silences. + MaxSilences func() int + // MaxSilenceSizeBytes is the maximum size of an individual silence as + // stored on disk. + MaxSilenceSizeBytes func() int +} + // MaintenanceFunc represents the function to run as part of the periodic maintenance for silences. // It returns the size of the snapshot taken or an error if it failed. type MaintenanceFunc func() (int64, error) @@ -230,7 +241,7 @@ func newSilenceMetricByState(s *Silences, st types.SilenceState) prometheus.Gaug func() float64 { count, err := s.CountState(st) if err != nil { - level.Error(s.logger).Log("msg", "Counting silences failed", "err", err) + s.logger.Error("Counting silences failed", "err", err) } return float64(count) }, @@ -271,8 +282,12 @@ func newMetrics(r prometheus.Registerer, s *Silences) *metrics { Help: "How many silence received queries did not succeed.", }) m.queryDuration = prometheus.NewHistogram(prometheus.HistogramOpts{ - Name: "alertmanager_silences_query_duration_seconds", - Help: "Duration of silence query evaluation.", + Name: "alertmanager_silences_query_duration_seconds", + Help: "Duration of silence query evaluation.", + Buckets: prometheus.DefBuckets, + NativeHistogramBucketFactor: 1.1, + NativeHistogramMaxBucketNumber: 100, + NativeHistogramMinResetDuration: 1 * time.Hour, }) m.propagatedMessagesTotal = prometheus.NewCounter(prometheus.CounterOpts{ Name: "alertmanager_silences_gossip_messages_propagated_total", @@ -314,15 +329,16 @@ type Options struct { // Retention time for newly created Silences. Silences may be // garbage collected after the given duration after they ended. Retention time.Duration + Limits Limits // A logger used by background processing. - Logger log.Logger + Logger *slog.Logger Metrics prometheus.Registerer } func (o *Options) validate() error { if o.SnapshotFile != "" && o.SnapshotReader != nil { - return fmt.Errorf("only one of SnapshotFile and SnapshotReader must be set") + return errors.New("only one of SnapshotFile and SnapshotReader must be set") } return nil } @@ -334,10 +350,11 @@ func New(o Options) (*Silences, error) { } s := &Silences{ - clock: clock.New(), + clock: quartz.NewReal(), mc: matcherCache{}, - logger: log.NewNopLogger(), + logger: promslog.NewNopLogger(), retention: o.Retention, + limits: o.Limits, broadcast: func([]byte) {}, st: state{}, } @@ -352,7 +369,7 @@ func New(o Options) (*Silences, error) { if !os.IsNotExist(err) { return nil, err } - level.Debug(s.logger).Log("msg", "silences snapshot file doesn't exist", "err", err) + s.logger.Debug("silences snapshot file doesn't exist", "err", err) } else { o.SnapshotReader = r defer r.Close() @@ -377,10 +394,10 @@ func (s *Silences) nowUTC() time.Time { // If not nil, the last argument is an override for what to do as part of the maintenance - for advanced usage. func (s *Silences) Maintenance(interval time.Duration, snapf string, stopc <-chan struct{}, override MaintenanceFunc) { if interval == 0 || stopc == nil { - level.Error(s.logger).Log("msg", "interval or stop signal are missing - not running maintenance") + s.logger.Error("interval or stop signal are missing - not running maintenance") return } - t := s.clock.Ticker(interval) + t := s.clock.NewTicker(interval) defer t.Stop() var doMaintenance MaintenanceFunc @@ -410,7 +427,7 @@ func (s *Silences) Maintenance(interval time.Duration, snapf string, stopc <-cha runMaintenance := func(do MaintenanceFunc) error { s.metrics.maintenanceTotal.Inc() - level.Debug(s.logger).Log("msg", "Running maintenance") + s.logger.Debug("Running maintenance") start := s.nowUTC() size, err := do() s.metrics.snapshotSize.Set(float64(size)) @@ -418,7 +435,7 @@ func (s *Silences) Maintenance(interval time.Duration, snapf string, stopc <-cha s.metrics.maintenanceErrorsTotal.Inc() return err } - level.Debug(s.logger).Log("msg", "Maintenance done", "duration", s.clock.Since(start), "size", size) + s.logger.Debug("Maintenance done", "duration", s.clock.Since(start), "size", size) return nil } @@ -429,7 +446,8 @@ Loop: break Loop case <-t.C: if err := runMaintenance(doMaintenance); err != nil { - level.Info(s.logger).Log("msg", "Running maintenance failed", "err", err) + // @tjhop: this should probably log at error level + s.logger.Info("Running maintenance failed", "err", err) } } } @@ -439,7 +457,8 @@ Loop: return } if err := runMaintenance(doMaintenance); err != nil { - level.Info(s.logger).Log("msg", "Creating shutdown snapshot failed", "err", err) + // @tjhop: this should probably log at error level + s.logger.Info("Creating shutdown snapshot failed", "err", err) } } @@ -461,7 +480,7 @@ func (s *Silences) GC() (int, error) { } if !sil.ExpiresAt.After(now) { delete(s.st, id) - delete(s.mc, sil.Silence) + delete(s.mc, sil.Silence.Id) n++ } } @@ -501,9 +520,6 @@ func matchesEmpty(m *pb.Matcher) bool { } func validateSilence(s *pb.Silence) error { - if s.Id == "" { - return errors.New("ID missing") - } if len(s.Matchers) == 0 { return errors.New("at least one matcher required") } @@ -527,9 +543,6 @@ func validateSilence(s *pb.Silence) error { if s.EndsAt.Before(s.StartsAt) { return errors.New("end time must not be before start time") } - if s.UpdatedAt.IsZero() { - return errors.New("invalid zero update timestamp") - } return nil } @@ -539,6 +552,16 @@ func cloneSilence(sil *pb.Silence) *pb.Silence { return &s } +func (s *Silences) checkSizeLimits(msil *pb.MeshSilence) error { + if s.limits.MaxSilenceSizeBytes != nil { + n := msil.Size() + if m := s.limits.MaxSilenceSizeBytes(); m > 0 && n > m { + return fmt.Errorf("silence exceeded maximum size: %d bytes (limit: %d bytes)", n, m) + } + } + return nil +} + func (s *Silences) getSilence(id string) (*pb.Silence, bool) { msil, ok := s.st[id] if !ok { @@ -547,67 +570,89 @@ func (s *Silences) getSilence(id string) (*pb.Silence, bool) { return msil.Silence, true } -func (s *Silences) setSilence(sil *pb.Silence, now time.Time, skipValidate bool) error { - sil.UpdatedAt = now - - if !skipValidate { - if err := validateSilence(sil); err != nil { - return fmt.Errorf("silence invalid: %w", err) - } - } - - msil := &pb.MeshSilence{ +func (s *Silences) toMeshSilence(sil *pb.Silence) *pb.MeshSilence { + return &pb.MeshSilence{ Silence: sil, ExpiresAt: sil.EndsAt.Add(s.retention), } +} + +func (s *Silences) setSilence(msil *pb.MeshSilence, now time.Time) error { b, err := marshalMeshSilence(msil) if err != nil { return err } - - if s.st.merge(msil, now) { + _, added := s.st.merge(msil, now) + if added { s.version++ } s.broadcast(b) - return nil } // Set the specified silence. If a silence with the ID already exists and the modification // modifies history, the old silence gets expired and a new one is created. -func (s *Silences) Set(sil *pb.Silence) (string, error) { +func (s *Silences) Set(sil *pb.Silence) error { s.mtx.Lock() defer s.mtx.Unlock() now := s.nowUTC() - prev, ok := s.getSilence(sil.Id) + if sil.StartsAt.IsZero() { + sil.StartsAt = now + } + if err := validateSilence(sil); err != nil { + return fmt.Errorf("invalid silence: %w", err) + } + + prev, ok := s.getSilence(sil.Id) if sil.Id != "" && !ok { - return "", ErrNotFound + return ErrNotFound } - if ok { - if canUpdate(prev, sil, now) { - return sil.Id, s.setSilence(sil, now, false) + + if ok && canUpdate(prev, sil, now) { + sil.UpdatedAt = now + msil := s.toMeshSilence(sil) + if err := s.checkSizeLimits(msil); err != nil { + return err } - if getState(prev, s.nowUTC()) != types.SilenceStateExpired { - // We cannot update the silence, expire the old one. - if err := s.expire(prev.Id); err != nil { - return "", fmt.Errorf("expire previous silence: %w", err) - } + return s.setSilence(msil, now) + } + + // If we got here it's either a new silence or a replacing one (which would + // also create a new silence) so we need to make sure we have capacity for + // the new silence. + if s.limits.MaxSilences != nil { + if m := s.limits.MaxSilences(); m > 0 && len(s.st)+1 > m { + return fmt.Errorf("exceeded maximum number of silences: %d (limit: %d)", len(s.st), m) } } - // If we got here it's either a new silence or a replacing one. + uid, err := uuid.NewV4() if err != nil { - return "", fmt.Errorf("generate uuid: %w", err) + return fmt.Errorf("generate uuid: %w", err) } sil.Id = uid.String() if sil.StartsAt.Before(now) { sil.StartsAt = now } + sil.UpdatedAt = now + + msil := s.toMeshSilence(sil) + if err := s.checkSizeLimits(msil); err != nil { + return err + } + + if ok && getState(prev, s.nowUTC()) != types.SilenceStateExpired { + // We cannot update the silence, expire the old one to leave a history of + // the silence before modification. + if err := s.expire(prev.Id); err != nil { + return fmt.Errorf("expire previous silence: %w", err) + } + } - return sil.Id, s.setSilence(sil, now, false) + return s.setSilence(msil, now) } // canUpdate returns true if silence a can be updated to b without @@ -665,10 +710,8 @@ func (s *Silences) expire(id string) error { sil.StartsAt = now sil.EndsAt = now } - - // Skip validation of the silence when expiring it. Without this, silences created - // with valid UTF-8 matchers cannot be expired when Alertmanager is run in classic mode. - return s.setSilence(sil, now, true) + sil.UpdatedAt = now + return s.setSilence(s.toMeshSilence(sil), now) } // QueryParam expresses parameters along which silences are queried. @@ -751,6 +794,9 @@ func (s *Silences) QueryOne(params ...QueryParam) (*pb.Silence, error) { // Query for silences based on the given query parameters. It returns the // resulting silences and the state version the result is based on. func (s *Silences) Query(params ...QueryParam) ([]*pb.Silence, int, error) { + s.mtx.Lock() + defer s.mtx.Unlock() + s.metrics.queriesTotal.Inc() defer prometheus.NewTimer(s.metrics.queryDuration).ObserveDuration() @@ -790,9 +836,6 @@ func (s *Silences) query(q *query, now time.Time) ([]*pb.Silence, int, error) { // the use of post-filter functions is the trivial solution for now. var res []*pb.Silence - s.mtx.Lock() - defer s.mtx.Unlock() - if q.ids != nil { for _, id := range q.ids { if s, ok := s.st[id]; ok { @@ -887,8 +930,11 @@ func (s *Silences) Merge(b []byte) error { now := s.nowUTC() for _, e := range st { - if merged := s.st.merge(e, now); merged { - s.version++ + merged, added := s.st.merge(e, now) + if merged { + if added { + s.version++ + } if !cluster.OversizedMessage(b) { // If this is the first we've seen the message and it's // not oversized, gossip it to other nodes. We don't @@ -896,7 +942,7 @@ func (s *Silences) Merge(b []byte) error { // all nodes already. s.broadcast(b) s.metrics.propagatedMessagesTotal.Inc() - level.Debug(s.logger).Log("msg", "Gossiping new silence", "silence", e) + s.logger.Debug("Gossiping new silence", "silence", e) } } } @@ -913,10 +959,13 @@ func (s *Silences) SetBroadcast(f func([]byte)) { type state map[string]*pb.MeshSilence -func (s state) merge(e *pb.MeshSilence, now time.Time) bool { +// merge returns two bools: the first is true when merge caused a state change. The second +// is true if that state change added a new silence. In other words, the second return is +// true whenever a silence with a new ID has been added to the state as a result of merge. +func (s state) merge(e *pb.MeshSilence, now time.Time) (bool, bool) { id := e.Silence.Id if e.ExpiresAt.Before(now) { - return false + return false, false } // Comments list was moved to a single comment. Apply upgrade // on silences received from peers. @@ -929,9 +978,9 @@ func (s state) merge(e *pb.MeshSilence, now time.Time) bool { prev, ok := s[id] if !ok || prev.Silence.UpdatedAt.Before(e.Silence.UpdatedAt) { s[id] = e - return true + return true, !ok } - return false + return false, false } func (s state) MarshalBinary() ([]byte, error) { diff --git a/vendor/github.com/prometheus/alertmanager/store/store.go b/vendor/github.com/prometheus/alertmanager/store/store.go index 83f1495a0f..e4275aa1f5 100644 --- a/vendor/github.com/prometheus/alertmanager/store/store.go +++ b/vendor/github.com/prometheus/alertmanager/store/store.go @@ -34,21 +34,21 @@ var ErrNotFound = errors.New("alert not found") type Alerts struct { sync.Mutex c map[model.Fingerprint]*types.Alert - cb func([]*types.Alert) + cb func([]types.Alert) } // NewAlerts returns a new Alerts struct. func NewAlerts() *Alerts { a := &Alerts{ c: make(map[model.Fingerprint]*types.Alert), - cb: func(_ []*types.Alert) {}, + cb: func(_ []types.Alert) {}, } return a } // SetGCCallback sets a GC callback to be executed after each GC. -func (a *Alerts) SetGCCallback(cb func([]*types.Alert)) { +func (a *Alerts) SetGCCallback(cb func([]types.Alert)) { a.Lock() defer a.Unlock() @@ -64,23 +64,34 @@ func (a *Alerts) Run(ctx context.Context, interval time.Duration) { case <-ctx.Done(): return case <-t.C: - a.gc() + a.GC() } } } -func (a *Alerts) gc() { +// GC deletes resolved alerts and returns them. +func (a *Alerts) GC() []types.Alert { a.Lock() - defer a.Unlock() - - var resolved []*types.Alert + var resolved []types.Alert for fp, alert := range a.c { if alert.Resolved() { delete(a.c, fp) - resolved = append(resolved, alert) + resolved = append(resolved, types.Alert{ + Alert: model.Alert{ + Labels: alert.Labels.Clone(), + Annotations: alert.Annotations.Clone(), + StartsAt: alert.StartsAt, + EndsAt: alert.EndsAt, + GeneratorURL: alert.GeneratorURL, + }, + UpdatedAt: alert.UpdatedAt, + Timeout: alert.Timeout, + }) } } + a.Unlock() a.cb(resolved) + return resolved } // Get returns the Alert with the matching fingerprint, or an error if it is @@ -105,12 +116,17 @@ func (a *Alerts) Set(alert *types.Alert) error { return nil } -// Delete removes the Alert with the matching fingerprint from the store. -func (a *Alerts) Delete(fp model.Fingerprint) error { +// DeleteIfNotModified deletes the slice of Alerts from the store if not +// modified. +func (a *Alerts) DeleteIfNotModified(alerts types.AlertSlice) error { a.Lock() defer a.Unlock() - - delete(a.c, fp) + for _, alert := range alerts { + fp := alert.Fingerprint() + if other, ok := a.c[fp]; ok && alert.UpdatedAt == other.UpdatedAt { + delete(a.c, fp) + } + } return nil } diff --git a/vendor/github.com/prometheus/alertmanager/template/Dockerfile b/vendor/github.com/prometheus/alertmanager/template/Dockerfile index 19d4be51a9..43b728d18c 100644 --- a/vendor/github.com/prometheus/alertmanager/template/Dockerfile +++ b/vendor/github.com/prometheus/alertmanager/template/Dockerfile @@ -1,7 +1,7 @@ -FROM node +FROM node:20-alpine ENV NODE_PATH="/usr/local/lib/node_modules" -RUN npm install juice -g +RUN npm install juice@10.0.1 -g ENTRYPOINT [""] diff --git a/vendor/github.com/prometheus/alertmanager/template/Makefile b/vendor/github.com/prometheus/alertmanager/template/Makefile index 93e0d4985b..a62721b9fe 100644 --- a/vendor/github.com/prometheus/alertmanager/template/Makefile +++ b/vendor/github.com/prometheus/alertmanager/template/Makefile @@ -1,4 +1,4 @@ -DOCKER_IMG := altermanager-template +DOCKER_IMG := alertmanager-template DOCKER_RUN_CURRENT_USER := docker run --user=$(shell id -u $(USER)):$(shell id -g $(USER)) DOCKER_CMD := $(DOCKER_RUN_CURRENT_USER) --rm -t -v $(PWD):/app -w /app $(DOCKER_IMG) diff --git a/vendor/github.com/prometheus/alertmanager/template/default.tmpl b/vendor/github.com/prometheus/alertmanager/template/default.tmpl index 8b2bb7470e..57e877c0c2 100644 --- a/vendor/github.com/prometheus/alertmanager/template/default.tmpl +++ b/vendor/github.com/prometheus/alertmanager/template/default.tmpl @@ -123,6 +123,7 @@ Alerts Resolved: {{ end }} {{ end }} +{{ define "discord.default.content" }}{{ end }} {{ define "discord.default.title" }}{{ template "__subject" . }}{{ end }} {{ define "discord.default.message" }} {{ if gt (len .Alerts.Firing) 0 }} @@ -158,3 +159,61 @@ Alerts Resolved: {{ template "__text_alert_list_markdown" .Alerts.Resolved }} {{ end }} {{ end }} + +{{ define "msteamsv2.default.title" }}{{ template "__subject" . }}{{ end }} +{{ define "msteamsv2.default.text" }} +{{ if gt (len .Alerts.Firing) 0 }} +# Alerts Firing: +{{ template "__text_alert_list_markdown" .Alerts.Firing }} +{{ end }} +{{ if gt (len .Alerts.Resolved) 0 }} +# Alerts Resolved: +{{ template "__text_alert_list_markdown" .Alerts.Resolved }} +{{ end }} +{{ end }} + +{{ define "jira.default.summary" }}{{ template "__subject" . }}{{ end }} +{{ define "jira.default.description" }} +{{ if gt (len .Alerts.Firing) 0 }} +# Alerts Firing: +{{ template "__text_alert_list_markdown" .Alerts.Firing }} +{{ end }} +{{ if gt (len .Alerts.Resolved) 0 }} +# Alerts Resolved: +{{ template "__text_alert_list_markdown" .Alerts.Resolved }} +{{ end }} +{{ end }} + +{{- define "jira.default.priority" -}} +{{- $priority := "" }} +{{- range .Alerts.Firing -}} + {{- $severity := index .Labels "severity" -}} + {{- if (eq $severity "critical") -}} + {{- $priority = "High" -}} + {{- else if (and (eq $severity "warning") (ne $priority "High")) -}} + {{- $priority = "Medium" -}} + {{- else if (and (eq $severity "info") (eq $priority "")) -}} + {{- $priority = "Low" -}} + {{- end -}} +{{- end -}} +{{- if eq $priority "" -}} + {{- range .Alerts.Resolved -}} + {{- $severity := index .Labels "severity" -}} + {{- if (eq $severity "critical") -}} + {{- $priority = "High" -}} + {{- else if (and (eq $severity "warning") (ne $priority "High")) -}} + {{- $priority = "Medium" -}} + {{- else if (and (eq $severity "info") (eq $priority "")) -}} + {{- $priority = "Low" -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- $priority -}} +{{- end -}} + +{{ define "rocketchat.default.title" }}{{ template "__subject" . }}{{ end }} +{{ define "rocketchat.default.alias" }}{{ template "__alertmanager" . }}{{ end }} +{{ define "rocketchat.default.titlelink" }}{{ template "__alertmanagerURL" . }}{{ end }} +{{ define "rocketchat.default.emoji" }}{{ end }} +{{ define "rocketchat.default.iconurl" }}{{ end }} +{{ define "rocketchat.default.text" }}{{ end }} diff --git a/vendor/github.com/prometheus/alertmanager/template/template.go b/vendor/github.com/prometheus/alertmanager/template/template.go index 5172ba92a7..92f8323e25 100644 --- a/vendor/github.com/prometheus/alertmanager/template/template.go +++ b/vendor/github.com/prometheus/alertmanager/template/template.go @@ -26,6 +26,7 @@ import ( tmpltext "text/template" "time" + commonTemplates "github.com/prometheus/common/helpers/templates" "github.com/prometheus/common/model" "golang.org/x/text/cases" "golang.org/x/text/language" @@ -192,6 +193,20 @@ var DefaultFuncs = FuncMap{ "stringSlice": func(s ...string) []string { return s }, + // date returns the text representation of the time in the specified format. + "date": func(fmt string, t time.Time) string { + return t.Format(fmt) + }, + // tz returns the time in the timezone. + "tz": func(name string, t time.Time) (time.Time, error) { + loc, err := time.LoadLocation(name) + if err != nil { + return time.Time{}, err + } + return t.In(loc), nil + }, + "since": time.Since, + "humanizeDuration": commonTemplates.HumanizeDuration, } // Pair is a key/value string pair. diff --git a/vendor/github.com/prometheus/alertmanager/timeinterval/timeinterval.go b/vendor/github.com/prometheus/alertmanager/timeinterval/timeinterval.go index fe8c97d729..caf81485ce 100644 --- a/vendor/github.com/prometheus/alertmanager/timeinterval/timeinterval.go +++ b/vendor/github.com/prometheus/alertmanager/timeinterval/timeinterval.go @@ -33,21 +33,23 @@ type Intervener struct { intervals map[string][]TimeInterval } -func (i *Intervener) Mutes(names []string, now time.Time) (bool, error) { +// Mutes implements the TimeMuter interface. +func (i *Intervener) Mutes(names []string, now time.Time) (bool, []string, error) { + var in []string for _, name := range names { interval, ok := i.intervals[name] if !ok { - return false, fmt.Errorf("time interval %s doesn't exist in config", name) + return false, nil, fmt.Errorf("time interval %s doesn't exist in config", name) } for _, ti := range interval { if ti.ContainsTime(now.UTC()) { - return true, nil + in = append(in, name) } } } - return false, nil + return len(in) > 0, in, nil } func NewIntervener(ti map[string][]TimeInterval) *Intervener { @@ -383,7 +385,7 @@ func (r WeekdayRange) MarshalYAML() (interface{}, error) { // MarshalText implements the econding.TextMarshaler interface for WeekdayRange. // It converts the range into a colon-separated string, or a single weekday if possible. -// e.g. "monday:friday" or "saturday". +// E.g. "monday:friday" or "saturday". func (r WeekdayRange) MarshalText() ([]byte, error) { beginStr, ok := daysOfWeekInv[r.Begin] if !ok { @@ -450,7 +452,7 @@ func (tz Location) MarshalJSON() (out []byte, err error) { // MarshalText implements the encoding.TextMarshaler interface for InclusiveRange. // It converts the struct into a colon-separated string, or a single element if -// appropriate. e.g. "monday:friday" or "monday" +// appropriate. E.g. "monday:friday" or "monday". func (ir InclusiveRange) MarshalText() ([]byte, error) { if ir.Begin == ir.End { return []byte(strconv.Itoa(ir.Begin)), nil diff --git a/vendor/github.com/prometheus/alertmanager/types/types.go b/vendor/github.com/prometheus/alertmanager/types/types.go index 54a889ab9c..727ac320e3 100644 --- a/vendor/github.com/prometheus/alertmanager/types/types.go +++ b/vendor/github.com/prometheus/alertmanager/types/types.go @@ -22,7 +22,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/model" - "github.com/prometheus/alertmanager/matchers/compat" + "github.com/prometheus/alertmanager/matcher/compat" "github.com/prometheus/alertmanager/pkg/labels" ) @@ -52,9 +52,17 @@ type AlertStatus struct { silencesVersion int } -// Marker helps to mark alerts as silenced and/or inhibited. +// groupStatus stores the state of the group, and, as applicable, the names +// of all active and mute time intervals that are muting it. +type groupStatus struct { + // mutedBy contains the names of all active and mute time intervals that + // are muting it. + mutedBy []string +} + +// AlertMarker helps to mark alerts as silenced and/or inhibited. // All methods are goroutine-safe. -type Marker interface { +type AlertMarker interface { // SetActiveOrSilenced replaces the previous SilencedBy by the provided IDs of // active and pending silences, including the version number of the // silences state. The set of provided IDs is supposed to represent the @@ -92,24 +100,74 @@ type Marker interface { Inhibited(model.Fingerprint) ([]string, bool) } -// NewMarker returns an instance of a Marker implementation. -func NewMarker(r prometheus.Registerer) Marker { - m := &memMarker{ - m: map[model.Fingerprint]*AlertStatus{}, - } +// GroupMarker helps to mark groups as active or muted. +// All methods are goroutine-safe. +// +// TODO(grobinson): routeID is used in Muted and SetMuted because groupKey +// is not unique (see #3817). Once groupKey uniqueness is fixed routeID can +// be removed from the GroupMarker interface. +type GroupMarker interface { + // Muted returns true if the group is muted, otherwise false. If the group + // is muted then it also returns the names of the time intervals that muted + // it. + Muted(routeID, groupKey string) ([]string, bool) + + // SetMuted marks the group as muted, and sets the names of the time + // intervals that mute it. If the list of names is nil or the empty slice + // then the muted marker is removed. + SetMuted(routeID, groupKey string, timeIntervalNames []string) + + // DeleteByGroupKey removes all markers for the GroupKey. + DeleteByGroupKey(routeID, groupKey string) +} +// NewMarker returns an instance of a AlertMarker implementation. +func NewMarker(r prometheus.Registerer) *MemMarker { + m := &MemMarker{ + alerts: map[model.Fingerprint]*AlertStatus{}, + groups: map[string]*groupStatus{}, + } m.registerMetrics(r) - return m } -type memMarker struct { - m map[model.Fingerprint]*AlertStatus +type MemMarker struct { + alerts map[model.Fingerprint]*AlertStatus + groups map[string]*groupStatus mtx sync.RWMutex } -func (m *memMarker) registerMetrics(r prometheus.Registerer) { +// Muted implements GroupMarker. +func (m *MemMarker) Muted(routeID, groupKey string) ([]string, bool) { + m.mtx.Lock() + defer m.mtx.Unlock() + status, ok := m.groups[routeID+groupKey] + if !ok { + return nil, false + } + return status.mutedBy, len(status.mutedBy) > 0 +} + +// SetMuted implements GroupMarker. +func (m *MemMarker) SetMuted(routeID, groupKey string, timeIntervalNames []string) { + m.mtx.Lock() + defer m.mtx.Unlock() + status, ok := m.groups[routeID+groupKey] + if !ok { + status = &groupStatus{} + m.groups[routeID+groupKey] = status + } + status.mutedBy = timeIntervalNames +} + +func (m *MemMarker) DeleteByGroupKey(routeID, groupKey string) { + m.mtx.Lock() + defer m.mtx.Unlock() + delete(m.groups, routeID+groupKey) +} + +func (m *MemMarker) registerMetrics(r prometheus.Registerer) { newMarkedAlertMetricByState := func(st AlertState) prometheus.GaugeFunc { return prometheus.NewGaugeFunc( prometheus.GaugeOpts{ @@ -132,17 +190,17 @@ func (m *memMarker) registerMetrics(r prometheus.Registerer) { r.MustRegister(alertStateUnprocessed) } -// Count implements Marker. -func (m *memMarker) Count(states ...AlertState) int { +// Count implements AlertMarker. +func (m *MemMarker) Count(states ...AlertState) int { m.mtx.RLock() defer m.mtx.RUnlock() if len(states) == 0 { - return len(m.m) + return len(m.alerts) } var count int - for _, status := range m.m { + for _, status := range m.alerts { for _, state := range states { if status.State == state { count++ @@ -152,15 +210,15 @@ func (m *memMarker) Count(states ...AlertState) int { return count } -// SetActiveOrSilenced implements Marker. -func (m *memMarker) SetActiveOrSilenced(alert model.Fingerprint, version int, activeIDs, pendingIDs []string) { +// SetActiveOrSilenced implements AlertMarker. +func (m *MemMarker) SetActiveOrSilenced(alert model.Fingerprint, version int, activeIDs, pendingIDs []string) { m.mtx.Lock() defer m.mtx.Unlock() - s, found := m.m[alert] + s, found := m.alerts[alert] if !found { s = &AlertStatus{} - m.m[alert] = s + m.alerts[alert] = s } s.SilencedBy = activeIDs s.pendingSilences = pendingIDs @@ -177,15 +235,15 @@ func (m *memMarker) SetActiveOrSilenced(alert model.Fingerprint, version int, ac s.State = AlertStateSuppressed } -// SetInhibited implements Marker. -func (m *memMarker) SetInhibited(alert model.Fingerprint, ids ...string) { +// SetInhibited implements AlertMarker. +func (m *MemMarker) SetInhibited(alert model.Fingerprint, ids ...string) { m.mtx.Lock() defer m.mtx.Unlock() - s, found := m.m[alert] + s, found := m.alerts[alert] if !found { s = &AlertStatus{} - m.m[alert] = s + m.alerts[alert] = s } s.InhibitedBy = ids @@ -200,12 +258,12 @@ func (m *memMarker) SetInhibited(alert model.Fingerprint, ids ...string) { s.State = AlertStateSuppressed } -// Status implements Marker. -func (m *memMarker) Status(alert model.Fingerprint) AlertStatus { +// Status implements AlertMarker. +func (m *MemMarker) Status(alert model.Fingerprint) AlertStatus { m.mtx.RLock() defer m.mtx.RUnlock() - if s, found := m.m[alert]; found { + if s, found := m.alerts[alert]; found { return *s } return AlertStatus{ @@ -215,26 +273,26 @@ func (m *memMarker) Status(alert model.Fingerprint) AlertStatus { } } -// Delete implements Marker. -func (m *memMarker) Delete(alert model.Fingerprint) { +// Delete implements AlertMarker. +func (m *MemMarker) Delete(alert model.Fingerprint) { m.mtx.Lock() defer m.mtx.Unlock() - delete(m.m, alert) + delete(m.alerts, alert) } -// Unprocessed implements Marker. -func (m *memMarker) Unprocessed(alert model.Fingerprint) bool { +// Unprocessed implements AlertMarker. +func (m *MemMarker) Unprocessed(alert model.Fingerprint) bool { return m.Status(alert).State == AlertStateUnprocessed } -// Active implements Marker. -func (m *memMarker) Active(alert model.Fingerprint) bool { +// Active implements AlertMarker. +func (m *MemMarker) Active(alert model.Fingerprint) bool { return m.Status(alert).State == AlertStateActive } -// Inhibited implements Marker. -func (m *memMarker) Inhibited(alert model.Fingerprint) ([]string, bool) { +// Inhibited implements AlertMarker. +func (m *MemMarker) Inhibited(alert model.Fingerprint) ([]string, bool) { s := m.Status(alert) return s.InhibitedBy, s.State == AlertStateSuppressed && len(s.InhibitedBy) > 0 @@ -243,7 +301,7 @@ func (m *memMarker) Inhibited(alert model.Fingerprint) ([]string, bool) { // Silenced returns whether the alert for the given Fingerprint is in the // Silenced state, any associated silence IDs, and the silences state version // the result is based on. -func (m *memMarker) Silenced(alert model.Fingerprint) (activeIDs, pendingIDs []string, version int, silenced bool) { +func (m *MemMarker) Silenced(alert model.Fingerprint) (activeIDs, pendingIDs []string, version int, silenced bool) { s := m.Status(alert) return s.SilencedBy, s.pendingSilences, s.silencesVersion, s.State == AlertStateSuppressed && len(s.SilencedBy) > 0 @@ -410,15 +468,17 @@ func (a *Alert) Merge(o *Alert) *Alert { } // A Muter determines whether a given label set is muted. Implementers that -// maintain an underlying Marker are expected to update it during a call of +// maintain an underlying AlertMarker are expected to update it during a call of // Mutes. type Muter interface { Mutes(model.LabelSet) bool } -// TimeMuter determines if alerts should be muted based on the specified current time and active time interval on the route. +// A TimeMuter determines if the time is muted by one or more active or mute +// time intervals. If the time is muted, it returns true and the names of the +// time intervals that muted it. Otherwise, it returns false and a nil slice. type TimeMuter interface { - Mutes(timeIntervalName []string, now time.Time) (bool, error) + Mutes(timeIntervalNames []string, now time.Time) (bool, []string, error) } // A MuteFunc is a function that implements the Muter interface. @@ -458,7 +518,7 @@ type Silence struct { } // Expired return if the silence is expired -// meaning that both StartsAt and EndsAt are equal +// meaning that both StartsAt and EndsAt are equal. func (s *Silence) Expired() bool { return s.StartsAt.Equal(s.EndsAt) } diff --git a/vendor/github.com/prometheus/alertmanager/ui/web.go b/vendor/github.com/prometheus/alertmanager/ui/web.go index 3820625925..3b81135237 100644 --- a/vendor/github.com/prometheus/alertmanager/ui/web.go +++ b/vendor/github.com/prometheus/alertmanager/ui/web.go @@ -15,11 +15,11 @@ package ui import ( "fmt" + "log/slog" "net/http" _ "net/http/pprof" // Comment this line to disable pprof endpoint. "path" - "github.com/go-kit/log" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/common/route" @@ -27,7 +27,7 @@ import ( ) // Register registers handlers to serve files for the web interface. -func Register(r *route.Router, reloadCh chan<- chan error, logger log.Logger) { +func Register(r *route.Router, reloadCh chan<- chan error, logger *slog.Logger) { r.Get("/metrics", promhttp.Handler().ServeHTTP) r.Get("/", func(w http.ResponseWriter, req *http.Request) { diff --git a/vendor/github.com/prometheus/common/config/http_config.go b/vendor/github.com/prometheus/common/config/http_config.go index 57ec252adf..63809083ac 100644 --- a/vendor/github.com/prometheus/common/config/http_config.go +++ b/vendor/github.com/prometheus/common/config/http_config.go @@ -52,7 +52,8 @@ var ( http2Enabled: true, // 5 minutes is typically above the maximum sane scrape interval. So we can // use keepalive for all configurations. - idleConnTimeout: 5 * time.Minute, + idleConnTimeout: 5 * time.Minute, + newTLSConfigFunc: NewTLSConfigWithContext, } ) @@ -452,8 +453,12 @@ func (a *BasicAuth) UnmarshalYAML(unmarshal func(interface{}) error) error { // by net.Dialer. type DialContextFunc func(context.Context, string, string) (net.Conn, error) +// NewTLSConfigFunc returns tls.Config. +type NewTLSConfigFunc func(context.Context, *TLSConfig, ...TLSConfigOption) (*tls.Config, error) + type httpClientOptions struct { dialContextFunc DialContextFunc + newTLSConfigFunc NewTLSConfigFunc keepAlivesEnabled bool http2Enabled bool idleConnTimeout time.Duration @@ -473,13 +478,23 @@ func (f httpClientOptionFunc) applyToHTTPClientOptions(options *httpClientOption f(options) } -// WithDialContextFunc allows you to override func gets used for the actual dialing. The default is `net.Dialer.DialContext`. +// WithDialContextFunc allows you to override the func gets used for the dialing. +// The default is `net.Dialer.DialContext`. func WithDialContextFunc(fn DialContextFunc) HTTPClientOption { return httpClientOptionFunc(func(opts *httpClientOptions) { opts.dialContextFunc = fn }) } +// WithNewTLSConfigFunc allows you to override the func that creates the TLS config +// from the prometheus http config. +// The default is `NewTLSConfigWithContext`. +func WithNewTLSConfigFunc(newTLSConfigFunc NewTLSConfigFunc) HTTPClientOption { + return httpClientOptionFunc(func(opts *httpClientOptions) { + opts.newTLSConfigFunc = newTLSConfigFunc + }) +} + // WithKeepAlivesDisabled allows to disable HTTP keepalive. func WithKeepAlivesDisabled() HTTPClientOption { return httpClientOptionFunc(func(opts *httpClientOptions) { @@ -670,7 +685,7 @@ func NewRoundTripperFromConfigWithContext(ctx context.Context, cfg HTTPClientCon return rt, nil } - tlsConfig, err := NewTLSConfig(&cfg.TLSConfig, WithSecretManager(opts.secretManager)) + tlsConfig, err := opts.newTLSConfigFunc(ctx, &cfg.TLSConfig, WithSecretManager(opts.secretManager)) if err != nil { return nil, err } @@ -679,6 +694,7 @@ func NewRoundTripperFromConfigWithContext(ctx context.Context, cfg HTTPClientCon if err != nil { return nil, err } + if tlsSettings.immutable() { // No need for a RoundTripper that reloads the files automatically. return newRT(tlsConfig) diff --git a/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go b/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go index f1c495dd60..a21ed4ec1f 100644 --- a/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go +++ b/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go @@ -38,7 +38,7 @@ type EncoderOption func(*encoderOption) // WithCreatedLines is an EncoderOption that configures the OpenMetrics encoder // to include _created lines (See -// https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#counter-1). +// https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#counter-1). // Created timestamps can improve the accuracy of series reset detection, but // come with a bandwidth cost. // @@ -102,7 +102,7 @@ func WithUnit() EncoderOption { // // - According to the OM specs, the `# UNIT` line is optional, but if populated, // the unit has to be present in the metric name as its suffix: -// (see https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#unit). +// (see https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#unit). // However, in order to accommodate any potential scenario where such a change in the // metric name is not desirable, the users are here given the choice of either explicitly // opt in, in case they wish for the unit to be included in the output AND in the metric name diff --git a/vendor/github.com/prometheus/common/model/metric.go b/vendor/github.com/prometheus/common/model/metric.go index 0daca836af..5766107cf9 100644 --- a/vendor/github.com/prometheus/common/model/metric.go +++ b/vendor/github.com/prometheus/common/model/metric.go @@ -28,13 +28,13 @@ import ( var ( // NameValidationScheme determines the method of name validation to be used by - // all calls to IsValidMetricName() and LabelName IsValid(). Setting UTF-8 mode - // in isolation from other components that don't support UTF-8 may result in - // bugs or other undefined behavior. This value is intended to be set by - // UTF-8-aware binaries as part of their startup. To avoid need for locking, - // this value should be set once, ideally in an init(), before multiple - // goroutines are started. - NameValidationScheme = LegacyValidation + // all calls to IsValidMetricName() and LabelName IsValid(). Setting UTF-8 + // mode in isolation from other components that don't support UTF-8 may result + // in bugs or other undefined behavior. This value can be set to + // LegacyValidation during startup if a binary is not UTF-8-aware binaries. To + // avoid need for locking, this value should be set once, ideally in an + // init(), before multiple goroutines are started. + NameValidationScheme = UTF8Validation // 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 diff --git a/vendor/github.com/prometheus/common/promslog/slog.go b/vendor/github.com/prometheus/common/promslog/slog.go new file mode 100644 index 0000000000..6e8fbabce5 --- /dev/null +++ b/vendor/github.com/prometheus/common/promslog/slog.go @@ -0,0 +1,201 @@ +// 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. + +// Package promslog defines standardised ways to initialize the Go standard +// library's log/slog logger. +// It should typically only ever be imported by main packages. + +package promslog + +import ( + "fmt" + "io" + "log/slog" + "os" + "path/filepath" + "strconv" + "strings" +) + +type LogStyle string + +const ( + SlogStyle LogStyle = "slog" + GoKitStyle LogStyle = "go-kit" +) + +var ( + LevelFlagOptions = []string{"debug", "info", "warn", "error"} + FormatFlagOptions = []string{"logfmt", "json"} + + callerAddFunc = false + defaultWriter = os.Stderr + goKitStyleReplaceAttrFunc = func(groups []string, a slog.Attr) slog.Attr { + key := a.Key + switch key { + case slog.TimeKey: + a.Key = "ts" + + // This timestamp format differs from RFC3339Nano by using .000 instead + // of .999999999 which changes the timestamp from 9 variable to 3 fixed + // decimals (.130 instead of .130987456). + t := a.Value.Time() + a.Value = slog.StringValue(t.UTC().Format("2006-01-02T15:04:05.000Z07:00")) + case slog.SourceKey: + a.Key = "caller" + src, _ := a.Value.Any().(*slog.Source) + + switch callerAddFunc { + case true: + a.Value = slog.StringValue(filepath.Base(src.File) + "(" + filepath.Base(src.Function) + "):" + strconv.Itoa(src.Line)) + default: + a.Value = slog.StringValue(filepath.Base(src.File) + ":" + strconv.Itoa(src.Line)) + } + case slog.LevelKey: + a.Value = slog.StringValue(strings.ToLower(a.Value.String())) + default: + } + + return a + } + defaultReplaceAttrFunc = func(groups []string, a slog.Attr) slog.Attr { + key := a.Key + switch key { + case slog.TimeKey: + t := a.Value.Time() + a.Value = slog.TimeValue(t.UTC()) + case slog.SourceKey: + src, _ := a.Value.Any().(*slog.Source) + a.Value = slog.StringValue(filepath.Base(src.File) + ":" + strconv.Itoa(src.Line)) + default: + } + + return a + } +) + +// AllowedLevel is a settable identifier for the minimum level a log entry +// must be have. +type AllowedLevel struct { + s string + lvl *slog.LevelVar +} + +func (l *AllowedLevel) UnmarshalYAML(unmarshal func(interface{}) error) error { + var s string + type plain string + if err := unmarshal((*plain)(&s)); err != nil { + return err + } + if s == "" { + return nil + } + lo := &AllowedLevel{} + if err := lo.Set(s); err != nil { + return err + } + *l = *lo + return nil +} + +func (l *AllowedLevel) String() string { + return l.s +} + +// Set updates the value of the allowed level. +func (l *AllowedLevel) Set(s string) error { + if l.lvl == nil { + l.lvl = &slog.LevelVar{} + } + + switch strings.ToLower(s) { + case "debug": + l.lvl.Set(slog.LevelDebug) + callerAddFunc = true + case "info": + l.lvl.Set(slog.LevelInfo) + callerAddFunc = false + case "warn": + l.lvl.Set(slog.LevelWarn) + callerAddFunc = false + case "error": + l.lvl.Set(slog.LevelError) + callerAddFunc = false + default: + return fmt.Errorf("unrecognized log level %s", s) + } + l.s = s + return nil +} + +// AllowedFormat is a settable identifier for the output format that the logger can have. +type AllowedFormat struct { + s string +} + +func (f *AllowedFormat) String() string { + return f.s +} + +// Set updates the value of the allowed format. +func (f *AllowedFormat) Set(s string) error { + switch s { + case "logfmt", "json": + f.s = s + default: + return fmt.Errorf("unrecognized log format %s", s) + } + return nil +} + +// Config is a struct containing configurable settings for the logger +type Config struct { + Level *AllowedLevel + Format *AllowedFormat + Style LogStyle + Writer io.Writer +} + +// New returns a new slog.Logger. Each logged line will be annotated +// with a timestamp. The output always goes to stderr. +func New(config *Config) *slog.Logger { + if config.Level == nil { + config.Level = &AllowedLevel{} + _ = config.Level.Set("info") + } + + if config.Writer == nil { + config.Writer = defaultWriter + } + + logHandlerOpts := &slog.HandlerOptions{ + Level: config.Level.lvl, + AddSource: true, + ReplaceAttr: defaultReplaceAttrFunc, + } + + if config.Style == GoKitStyle { + logHandlerOpts.ReplaceAttr = goKitStyleReplaceAttrFunc + } + + if config.Format != nil && config.Format.s == "json" { + return slog.New(slog.NewJSONHandler(config.Writer, logHandlerOpts)) + } + return slog.New(slog.NewTextHandler(config.Writer, logHandlerOpts)) +} + +// NewNopLogger is a convenience function to return an slog.Logger that writes +// to io.Discard. +func NewNopLogger() *slog.Logger { + return slog.New(slog.NewTextHandler(io.Discard, nil)) +} diff --git a/vendor/github.com/prometheus/exporter-toolkit/web/handler.go b/vendor/github.com/prometheus/exporter-toolkit/web/handler.go index c607a163a3..51da762c95 100644 --- a/vendor/github.com/prometheus/exporter-toolkit/web/handler.go +++ b/vendor/github.com/prometheus/exporter-toolkit/web/handler.go @@ -18,11 +18,11 @@ package web import ( "encoding/hex" "fmt" + "log/slog" "net/http" "strings" "sync" - "github.com/go-kit/log" "golang.org/x/crypto/bcrypt" ) @@ -78,7 +78,7 @@ HeadersLoop: type webHandler struct { tlsConfigPath string handler http.Handler - logger log.Logger + logger *slog.Logger cache *cache // bcryptMtx is there to ensure that bcrypt.CompareHashAndPassword is run // only once in parallel as this is CPU intensive. @@ -88,7 +88,7 @@ type webHandler struct { func (u *webHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { c, err := getConfig(u.tlsConfigPath) if err != nil { - u.logger.Log("msg", "Unable to parse configuration", "err", err) + u.logger.Error("Unable to parse configuration", "err", err.Error()) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } diff --git a/vendor/github.com/prometheus/exporter-toolkit/web/landing_page.go b/vendor/github.com/prometheus/exporter-toolkit/web/landing_page.go index 68266213ed..d417c15e0d 100644 --- a/vendor/github.com/prometheus/exporter-toolkit/web/landing_page.go +++ b/vendor/github.com/prometheus/exporter-toolkit/web/landing_page.go @@ -106,6 +106,10 @@ func NewLandingPage(c LandingConfig) (*LandingPageHandler, error) { } func (h *LandingPageHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/" { + http.NotFound(w, r) + return + } w.Header().Add("Content-Type", "text/html; charset=UTF-8") w.Write(h.landingPage) } diff --git a/vendor/github.com/prometheus/exporter-toolkit/web/tls_config.go b/vendor/github.com/prometheus/exporter-toolkit/web/tls_config.go index b16ded1d65..0730a938fd 100644 --- a/vendor/github.com/prometheus/exporter-toolkit/web/tls_config.go +++ b/vendor/github.com/prometheus/exporter-toolkit/web/tls_config.go @@ -18,6 +18,7 @@ import ( "crypto/x509" "errors" "fmt" + "log/slog" "net" "net/http" "net/url" @@ -27,8 +28,6 @@ import ( "strings" "github.com/coreos/go-systemd/v22/activation" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/mdlayher/vsock" config_util "github.com/prometheus/common/config" "golang.org/x/sync/errgroup" @@ -267,7 +266,7 @@ func ConfigToTLSConfig(c *TLSConfig) (*tls.Config, error) { // ServeMultiple starts the server on the given listeners. The FlagConfig is // also passed on to Serve. -func ServeMultiple(listeners []net.Listener, server *http.Server, flags *FlagConfig, logger log.Logger) error { +func ServeMultiple(listeners []net.Listener, server *http.Server, flags *FlagConfig, logger *slog.Logger) error { errs := new(errgroup.Group) for _, l := range listeners { l := l @@ -284,13 +283,13 @@ func ServeMultiple(listeners []net.Listener, server *http.Server, flags *FlagCon // Or instead uses systemd socket activated listeners if WebSystemdSocket in the // FlagConfig is true. // The FlagConfig is also passed on to ServeMultiple. -func ListenAndServe(server *http.Server, flags *FlagConfig, logger log.Logger) error { +func ListenAndServe(server *http.Server, flags *FlagConfig, logger *slog.Logger) error { if flags.WebSystemdSocket == nil && (flags.WebListenAddresses == nil || len(*flags.WebListenAddresses) == 0) { return ErrNoListeners } if flags.WebSystemdSocket != nil && *flags.WebSystemdSocket { - level.Info(logger).Log("msg", "Listening on systemd activated listeners instead of port listeners.") + logger.Info("Listening on systemd activated listeners instead of port listeners.") listeners, err := activation.Listeners() if err != nil { return err @@ -344,11 +343,11 @@ func parseVsockPort(address string) (uint32, error) { // Server starts the server on the given listener. Based on the file path // WebConfigFile in the FlagConfig, TLS or basic auth could be enabled. -func Serve(l net.Listener, server *http.Server, flags *FlagConfig, logger log.Logger) error { - level.Info(logger).Log("msg", "Listening on", "address", l.Addr().String()) +func Serve(l net.Listener, server *http.Server, flags *FlagConfig, logger *slog.Logger) error { + logger.Info("Listening on", "address", l.Addr().String()) tlsConfigPath := *flags.WebConfigFile if tlsConfigPath == "" { - level.Info(logger).Log("msg", "TLS is disabled.", "http2", false, "address", l.Addr().String()) + logger.Info("TLS is disabled.", "http2", false, "address", l.Addr().String()) return server.Serve(l) } @@ -381,10 +380,10 @@ func Serve(l net.Listener, server *http.Server, flags *FlagConfig, logger log.Lo server.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler)) } // Valid TLS config. - level.Info(logger).Log("msg", "TLS is enabled.", "http2", c.HTTPConfig.HTTP2, "address", l.Addr().String()) + logger.Info("TLS is enabled.", "http2", c.HTTPConfig.HTTP2, "address", l.Addr().String()) case errNoTLSConfig: // No TLS config, back to plain HTTP. - level.Info(logger).Log("msg", "TLS is disabled.", "http2", false, "address", l.Addr().String()) + logger.Info("TLS is disabled.", "http2", false, "address", l.Addr().String()) return server.Serve(l) default: // Invalid TLS config. @@ -512,6 +511,6 @@ func (tv *TLSVersion) MarshalYAML() (interface{}, error) { // tlsConfigPath, TLS or basic auth could be enabled. // // Deprecated: Use ListenAndServe instead. -func Listen(server *http.Server, flags *FlagConfig, logger log.Logger) error { +func Listen(server *http.Server, flags *FlagConfig, logger *slog.Logger) error { return ListenAndServe(server, flags, logger) } diff --git a/vendor/github.com/rs/cors/cors.go b/vendor/github.com/rs/cors/cors.go index da80d343b3..724f242ac6 100644 --- a/vendor/github.com/rs/cors/cors.go +++ b/vendor/github.com/rs/cors/cors.go @@ -364,9 +364,11 @@ func (c *Cors) handlePreflight(w http.ResponseWriter, r *http.Request) { // Note: the Fetch standard guarantees that at most one // Access-Control-Request-Headers header is present in the preflight request; // see step 5.2 in https://fetch.spec.whatwg.org/#cors-preflight-fetch-0. - reqHeaders, found := first(r.Header, "Access-Control-Request-Headers") - if found && !c.allowedHeadersAll && !c.allowedHeaders.Subsumes(reqHeaders[0]) { - c.logf(" Preflight aborted: headers '%v' not allowed", reqHeaders[0]) + // However, some gateways split that header into multiple headers of the same name; + // see https://github.com/rs/cors/issues/184. + reqHeaders, found := r.Header["Access-Control-Request-Headers"] + if found && !c.allowedHeadersAll && !c.allowedHeaders.Accepts(reqHeaders) { + c.logf(" Preflight aborted: headers '%v' not allowed", reqHeaders) return } if c.allowedOriginsAll { @@ -391,9 +393,7 @@ func (c *Cors) handlePreflight(w http.ResponseWriter, r *http.Request) { if len(c.maxAge) > 0 { headers["Access-Control-Max-Age"] = c.maxAge } - if c.Log != nil { - c.logf(" Preflight response headers: %v", headers) - } + c.logf(" Preflight response headers: %v", headers) } // handleActualRequest handles simple cross-origin requests, actual request or redirects @@ -440,9 +440,7 @@ func (c *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) { if c.allowCredentials { headers["Access-Control-Allow-Credentials"] = headerTrue } - if c.Log != nil { - c.logf(" Actual response added headers: %v", headers) - } + c.logf(" Actual response added headers: %v", headers) } // convenience method. checks if a logger is set. diff --git a/vendor/github.com/rs/cors/internal/sortedset.go b/vendor/github.com/rs/cors/internal/sortedset.go index 513da20f7d..844f3f9e03 100644 --- a/vendor/github.com/rs/cors/internal/sortedset.go +++ b/vendor/github.com/rs/cors/internal/sortedset.go @@ -52,46 +52,134 @@ func (set SortedSet) String() string { return strings.Join(elems, ",") } -// Subsumes reports whether csv is a sequence of comma-separated names that are -// - all elements of set, -// - sorted in lexicographically order, +// Accepts reports whether values is a sequence of list-based field values +// whose elements are +// - all members of set, +// - sorted in lexicographical order, // - unique. -func (set SortedSet) Subsumes(csv string) bool { - if csv == "" { - return true +func (set SortedSet) Accepts(values []string) bool { + var ( // effectively constant + maxLen = maxOWSBytes + set.maxLen + maxOWSBytes + 1 // +1 for comma + ) + var ( + posOfLastNameSeen = -1 + name string + commaFound bool + emptyElements int + ok bool + ) + for _, s := range values { + for { + // As a defense against maliciously long names in s, + // we process only a small number of s's leading bytes per iteration. + name, s, commaFound = cutAtComma(s, maxLen) + name, ok = trimOWS(name, maxOWSBytes) + if !ok { + return false + } + if name == "" { + // RFC 9110 requires recipients to tolerate + // "a reasonable number of empty list elements"; see + // https://httpwg.org/specs/rfc9110.html#abnf.extension.recipient. + emptyElements++ + if emptyElements > maxEmptyElements { + return false + } + if !commaFound { // We have now exhausted the names in s. + break + } + continue + } + pos, ok := set.m[name] + if !ok { + return false + } + // The names in s are expected to be sorted in lexicographical order + // and to each appear at most once. + // Therefore, the positions (in set) of the names that + // appear in s should form a strictly increasing sequence. + // If that's not actually the case, bail out. + if pos <= posOfLastNameSeen { + return false + } + posOfLastNameSeen = pos + if !commaFound { // We have now exhausted the names in s. + break + } + } + } + return true +} + +const ( + maxOWSBytes = 1 // number of leading/trailing OWS bytes tolerated + maxEmptyElements = 16 // number of empty list elements tolerated +) + +func cutAtComma(s string, n int) (before, after string, found bool) { + // Note: this implementation draws inspiration from strings.Cut's. + end := min(len(s), n) + if i := strings.IndexByte(s[:end], ','); i >= 0 { + after = s[i+1:] // deal with this first to save one bounds check + return s[:i], after, true + } + return s, "", false +} + +// TrimOWS trims up to n bytes of [optional whitespace (OWS)] +// from the start of and/or the end of s. +// If no more than n bytes of OWS are found at the start of s +// and no more than n bytes of OWS are found at the end of s, +// it returns the trimmed result and true. +// Otherwise, it returns the original string and false. +// +// [optional whitespace (OWS)]: https://httpwg.org/specs/rfc9110.html#whitespace +func trimOWS(s string, n int) (trimmed string, ok bool) { + if s == "" { + return s, true + } + trimmed, ok = trimRightOWS(s, n) + if !ok { + return s, false } - posOfLastNameSeen := -1 - chunkSize := set.maxLen + 1 // (to accommodate for at least one comma) - for { - // As a defense against maliciously long names in csv, - // we only process at most chunkSize bytes per iteration. - end := min(len(csv), chunkSize) - comma := strings.IndexByte(csv[:end], ',') - var name string - if comma == -1 { - name = csv - } else { - name = csv[:comma] + trimmed, ok = trimLeftOWS(trimmed, n) + if !ok { + return s, false + } + return trimmed, true +} + +func trimLeftOWS(s string, n int) (string, bool) { + sCopy := s + var i int + for len(s) > 0 { + if i > n { + return sCopy, false } - pos, found := set.m[name] - if !found { - return false + if !(s[0] == ' ' || s[0] == '\t') { + break } - // The names in csv are expected to be sorted in lexicographical order - // and appear at most once in csv. - // Therefore, the positions (in set) of the names that - // appear in csv should form a strictly increasing sequence. - // If that's not actually the case, bail out. - if pos <= posOfLastNameSeen { - return false + s = s[1:] + i++ + } + return s, true +} + +func trimRightOWS(s string, n int) (string, bool) { + sCopy := s + var i int + for len(s) > 0 { + if i > n { + return sCopy, false } - posOfLastNameSeen = pos - if comma < 0 { // We've now processed all the names in csv. + last := len(s) - 1 + if !(s[last] == ' ' || s[last] == '\t') { break } - csv = csv[comma+1:] + s = s[:last] + i++ } - return true + return s, true } // TODO: when updating go directive to 1.21 or later, diff --git a/vendor/github.com/rs/cors/utils.go b/vendor/github.com/rs/cors/utils.go index 7019f45cd9..41b0c2836a 100644 --- a/vendor/github.com/rs/cors/utils.go +++ b/vendor/github.com/rs/cors/utils.go @@ -1,7 +1,6 @@ package cors import ( - "net/http" "strings" ) @@ -24,11 +23,3 @@ func convert(s []string, f func(string) string) []string { } return out } - -func first(hdrs http.Header, k string) ([]string, bool) { - v, found := hdrs[k] - if !found || len(v) == 0 { - return nil, false - } - return v[:1], true -} diff --git a/vendor/github.com/shurcooL/vfsgen/.travis.yml b/vendor/github.com/shurcooL/vfsgen/.travis.yml deleted file mode 100644 index 6452acb283..0000000000 --- a/vendor/github.com/shurcooL/vfsgen/.travis.yml +++ /dev/null @@ -1,16 +0,0 @@ -sudo: false -language: go -go: - - 1.x - - master -matrix: - allow_failures: - - go: master - fast_finish: true -install: - - # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step). -script: - - go get -t -v ./... - - diff -n <(echo -n) <(gofmt -d -s .) - - go vet ./... - - go test -v -race ./... diff --git a/vendor/github.com/shurcooL/vfsgen/README.md b/vendor/github.com/shurcooL/vfsgen/README.md index 659a0a0344..bb4df2773f 100644 --- a/vendor/github.com/shurcooL/vfsgen/README.md +++ b/vendor/github.com/shurcooL/vfsgen/README.md @@ -1,7 +1,7 @@ vfsgen ====== -[![Build Status](https://travis-ci.org/shurcooL/vfsgen.svg?branch=master)](https://travis-ci.org/shurcooL/vfsgen) [![GoDoc](https://godoc.org/github.com/shurcooL/vfsgen?status.svg)](https://godoc.org/github.com/shurcooL/vfsgen) +[![Go Reference](https://pkg.go.dev/badge/github.com/shurcooL/vfsgen.svg)](https://pkg.go.dev/github.com/shurcooL/vfsgen) Package vfsgen takes an http.FileSystem (likely at `go generate` time) and generates Go code that statically implements the provided http.FileSystem. @@ -19,8 +19,8 @@ Features: Installation ------------ -```bash -go get -u github.com/shurcooL/vfsgen +```sh +go get github.com/shurcooL/vfsgen ``` Usage @@ -81,7 +81,7 @@ By using build tags, you can create a development mode where assets are loaded d For example, suppose your source filesystem is defined in a package with import path "example.com/project/data" as: ```Go -// +build dev +//go:build dev package data @@ -96,7 +96,7 @@ When built with the "dev" build tag, accessing `data.Assets` will read from disk A generate helper file assets_generate.go can be invoked via "//go:generate go run -tags=dev assets_generate.go" directive: ```Go -// +build ignore +//go:build ignore package main @@ -177,6 +177,7 @@ It strives to be the best in its class in terms of code quality and efficiency o ### Alternatives +- [`embed`](https://go.dev/pkg/embed) - Package embed provides access to files embedded in the running Go program. - [`go-bindata`](https://github.com/jteeuwen/go-bindata) - Reads from disk, generates Go code that provides access to data via a [custom API](https://github.com/jteeuwen/go-bindata#accessing-an-asset). - [`go-bindata-assetfs`](https://github.com/elazarl/go-bindata-assetfs) - Takes output of go-bindata and provides a wrapper that implements `http.FileSystem` interface (the same as what vfsgen outputs directly). - [`becky`](https://github.com/tv42/becky) - Embeds assets as string literals in Go source. @@ -195,6 +196,13 @@ Attribution This package was originally based on the excellent work by [@jteeuwen](https://github.com/jteeuwen) on [`go-bindata`](https://github.com/jteeuwen/go-bindata) and [@elazarl](https://github.com/elazarl) on [`go-bindata-assetfs`](https://github.com/elazarl/go-bindata-assetfs). +Directories +----------- + +| Path | Synopsis | +|------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------| +| [cmd/vfsgendev](https://pkg.go.dev/github.com/shurcooL/vfsgen/cmd/vfsgendev) | vfsgendev is a convenience tool for using vfsgen in a common development configuration. | + License ------- diff --git a/vendor/github.com/shurcooL/vfsgen/generator.go b/vendor/github.com/shurcooL/vfsgen/generator.go index c0067c5d36..99d910b7ea 100644 --- a/vendor/github.com/shurcooL/vfsgen/generator.go +++ b/vendor/github.com/shurcooL/vfsgen/generator.go @@ -5,7 +5,6 @@ import ( "compress/gzip" "errors" "io" - "io/ioutil" "net/http" "os" pathpkg "path" @@ -47,7 +46,7 @@ func Generate(input http.FileSystem, opt Options) error { } // Write output file (all at once). - err = ioutil.WriteFile(opt.Filename, buf.Bytes(), 0644) + err = os.WriteFile(opt.Filename, buf.Bytes(), 0644) return err } @@ -217,7 +216,7 @@ var t = template.Must(template.New("").Funcs(template.FuncMap{ }, }).Parse(`{{define "Header"}}// Code generated by vfsgen; DO NOT EDIT. -{{with .BuildTags}}// +build {{.}} +{{with .BuildTags}}//go:build {{.}} {{end}}package {{.PackageName}} @@ -226,7 +225,6 @@ import ( "compress/gzip" "fmt" "io" - "io/ioutil" "net/http" "os" pathpkg "path" @@ -358,7 +356,7 @@ func (f *vfsgen۰CompressedFile) Read(p []byte) (n int, err error) { } if f.grPos < f.seekPos { // Fast-forward. - _, err = io.CopyN(ioutil.Discard, f.gr, f.seekPos-f.grPos) + _, err = io.CopyN(io.Discard, f.gr, f.seekPos-f.grPos) if err != nil { return 0, err } @@ -386,9 +384,8 @@ func (f *vfsgen۰CompressedFile) Close() error { return f.gr.Close() } {{else}} -// We already imported "compress/gzip" and "io/ioutil", but ended up not using them. Avoid unused import error. -var _ = gzip.Reader{} -var _ = ioutil.Discard +// We already imported "compress/gzip" but ended up not using it. Avoid unused import error. +var _ *gzip.Reader {{end}}{{if .HasFile}} // vfsgen۰FileInfo is a static definition of an uncompressed file (because it's not worth gzip compressing). type vfsgen۰FileInfo struct { diff --git a/vendor/github.com/tjhop/slog-gokit/README.md b/vendor/github.com/tjhop/slog-gokit/README.md index d6b5e51de6..6addd47981 100644 --- a/vendor/github.com/tjhop/slog-gokit/README.md +++ b/vendor/github.com/tjhop/slog-gokit/README.md @@ -1,3 +1,8 @@ +[![license](https://img.shields.io/github/license/tjhop/slog-gokit)](https://github.com/tjhop/slog-gokit/blob/master/LICENSE) +[![Go Report Card](https://goreportcard.com/badge/github.com/tjhop/slog-gokit)](https://goreportcard.com/report/github.com/tjhop/slog-gokit) +[![golangci-lint](https://github.com/tjhop/slog-gokit/actions/workflows/golangci-lint.yaml/badge.svg)](https://github.com/tjhop/slog-gokit/actions/workflows/golangci-lint.yaml) +[![Latest Release](https://img.shields.io/github/v/release/tjhop/slog-gokit)](https://github.com/tjhop/slog-gokit/releases/latest) + # Go slog-gokit Adapter This library provides a custom slog.Handler that wraps a go-kit Logger, so that loggers created via `slog.New()` chain their log calls to the internal go-kit Logger. @@ -8,6 +13,12 @@ This library provides a custom slog.Handler that wraps a go-kit Logger, so that go get github.com/tjhop/slog-gokit ``` +## Documentation + +Documentation can be found here: + +https://pkg.go.dev/github.com/tjhop/slog-gokit + ## Example ```go @@ -29,7 +40,7 @@ func main() { slogger := slog.New(slgk.NewGoKitHandler(gklogger, nil)) slogger.WithGroup("example_group").With("foo", "bar").Info("hello world") - // The slog Logger produced logs at slog.LevelInfo by default. + // The slog Logger produces logs at slog.LevelInfo by default. // Optionally create an slog.Leveler to dynamically adjust the level of // the slog Logger. lvl := &slog.LevelVar{} diff --git a/vendor/github.com/tjhop/slog-gokit/handler.go b/vendor/github.com/tjhop/slog-gokit/handler.go index a926595292..d2b84a647c 100644 --- a/vendor/github.com/tjhop/slog-gokit/handler.go +++ b/vendor/github.com/tjhop/slog-gokit/handler.go @@ -41,6 +41,8 @@ func NewGoKitHandler(logger log.Logger, level slog.Leveler) slog.Handler { return &GoKitHandler{logger: logger, level: level} } +// Enabled returns true if the internal slog.Leveler is enabled for the +// provided log level. It implements slog.Handler. func (h *GoKitHandler) Enabled(_ context.Context, level slog.Level) bool { if h.level == nil { h.level = &slog.LevelVar{} // Info level by default. @@ -49,6 +51,10 @@ func (h *GoKitHandler) Enabled(_ context.Context, level slog.Level) bool { return level >= h.level.Level() } +// Handler take an slog.Record created by an slog.Logger and dispatches the log +// call to the internal go-kit logger. Groups and attributes created by slog +// are formatted and added to the log call as individual key/value pairs. It +// implements slog.Handler. func (h *GoKitHandler) Handle(_ context.Context, record slog.Record) error { if h.logger == nil { h.logger = defaultGoKitLogger @@ -77,6 +83,8 @@ func (h *GoKitHandler) Handle(_ context.Context, record slog.Record) error { return logger.Log(pairs...) } +// WithAttrs formats the provided attributes and caches them in the handler to +// attach to all future log calls. It implements slog.Handler. func (h *GoKitHandler) WithAttrs(attrs []slog.Attr) slog.Handler { pairs := make([]any, 0, 2*len(attrs)) for _, a := range attrs { @@ -95,6 +103,8 @@ func (h *GoKitHandler) WithAttrs(attrs []slog.Attr) slog.Handler { } } +// WithGroup sets the group prefix string and caches it within the handler to +// use to prefix all future log attribute pairs. It implements slog.Handler. func (h *GoKitHandler) WithGroup(name string) slog.Handler { if name == "" { return h @@ -120,11 +130,25 @@ func appendPair(pairs []any, groupPrefix string, attr slog.Attr) []any { switch attr.Value.Kind() { case slog.KindGroup: - if attr.Key != "" { - groupPrefix = groupPrefix + "." + attr.Key - } - for _, a := range attr.Value.Group() { - pairs = appendPair(pairs, groupPrefix, a) + attrs := attr.Value.Group() + if len(attrs) > 0 { + // Only process groups that have non-empty attributes + // to properly conform to slog.Handler interface + // contract. + + if attr.Key != "" { + // If a group's key is empty, attributes should + // be inlined to properly conform to + // slog.Handler interface contract. + if groupPrefix != "" { + groupPrefix = groupPrefix + "." + attr.Key + } else { + groupPrefix = attr.Key + } + } + for _, a := range attrs { + pairs = appendPair(pairs, groupPrefix, a) + } } default: key := attr.Key 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 ca6efc5136..15c99a2c28 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.17" + Version = "3.5.18" APIVersion = "unknown" // Git SHA Value will be set during build diff --git a/vendor/go.etcd.io/etcd/client/v3/lease.go b/vendor/go.etcd.io/etcd/client/v3/lease.go index 4e7d1caf83..4877ee9496 100644 --- a/vendor/go.etcd.io/etcd/client/v3/lease.go +++ b/vendor/go.etcd.io/etcd/client/v3/lease.go @@ -263,6 +263,12 @@ func (l *lessor) Leases(ctx context.Context) (*LeaseLeasesResponse, error) { return nil, ContextError(ctx, err) } +// To identify the context passed to `KeepAlive`, a key/value pair is +// attached to the context. The key is a `keepAliveCtxKey` object, and +// the value is the pointer to the context object itself, ensuring +// uniqueness as each context has a unique memory address. +type keepAliveCtxKey struct{} + func (l *lessor) KeepAlive(ctx context.Context, id LeaseID) (<-chan *LeaseKeepAliveResponse, error) { ch := make(chan *LeaseKeepAliveResponse, LeaseResponseChSize) @@ -277,6 +283,10 @@ func (l *lessor) KeepAlive(ctx context.Context, id LeaseID) (<-chan *LeaseKeepAl default: } ka, ok := l.keepAlives[id] + + if ctx.Done() != nil { + ctx = context.WithValue(ctx, keepAliveCtxKey{}, &ctx) + } if !ok { // create fresh keep alive ka = &keepAlive{ @@ -347,7 +357,7 @@ func (l *lessor) keepAliveCtxCloser(ctx context.Context, id LeaseID, donec <-cha // close channel and remove context if still associated with keep alive for i, c := range ka.ctxs { - if c == ctx { + if c.Value(keepAliveCtxKey{}) == ctx.Value(keepAliveCtxKey{}) { close(ka.chs[i]) ka.ctxs = append(ka.ctxs[:i], ka.ctxs[i+1:]...) ka.chs = append(ka.chs[:i], ka.chs[i+1:]...) diff --git a/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1/logs.pb.go b/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1/logs.pb.go index 65b11fbe28..1fb0f2b685 100644 --- a/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1/logs.pb.go +++ b/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1/logs.pb.go @@ -228,7 +228,8 @@ type ResourceLogs struct { // A list of ScopeLogs that originate from a resource. ScopeLogs []*ScopeLogs `protobuf:"bytes,2,rep,name=scope_logs,json=scopeLogs,proto3" json:"scope_logs,omitempty"` // The Schema URL, if known. This is the identifier of the Schema that the resource data - // is recorded in. To learn more about Schema URL see + // is recorded in. Notably, the last part of the URL path is the version number of the + // schema: http[s]://server[:port]/path/. To learn more about Schema URL see // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to the data in the "resource" field. It does not apply // to the data in the "scope_logs" field which have their own schema_url field. @@ -305,7 +306,8 @@ type ScopeLogs struct { // A list of log records. LogRecords []*LogRecord `protobuf:"bytes,2,rep,name=log_records,json=logRecords,proto3" json:"log_records,omitempty"` // The Schema URL, if known. This is the identifier of the Schema that the log data - // is recorded in. To learn more about Schema URL see + // is recorded in. Notably, the last part of the URL path is the version number of the + // schema: http[s]://server[:port]/path/. To learn more about Schema URL see // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to all logs in the "logs" field. SchemaUrl string `protobuf:"bytes,3,opt,name=schema_url,json=schemaUrl,proto3" json:"schema_url,omitempty"` @@ -434,6 +436,19 @@ type LogRecord struct { // - the field is not present, // - the field contains an invalid value. SpanId go_opentelemetry_io_collector_pdata_internal_data.SpanID `protobuf:"bytes,10,opt,name=span_id,json=spanId,proto3,customtype=go.opentelemetry.io/collector/pdata/internal/data.SpanID" json:"span_id"` + // A unique identifier of event category/type. + // All events with the same event_name are expected to conform to the same + // schema for both their attributes and their body. + // + // Recommended to be fully qualified and short (no longer than 256 characters). + // + // Presence of event_name on the log record identifies this record + // as an event. + // + // [Optional]. + // + // Status: [Development] + EventName string `protobuf:"bytes,12,opt,name=event_name,json=eventName,proto3" json:"event_name,omitempty"` } func (m *LogRecord) Reset() { *m = LogRecord{} } @@ -525,6 +540,13 @@ func (m *LogRecord) GetFlags() uint32 { return 0 } +func (m *LogRecord) GetEventName() string { + if m != nil { + return m.EventName + } + return "" +} + func init() { proto.RegisterEnum("opentelemetry.proto.logs.v1.SeverityNumber", SeverityNumber_name, SeverityNumber_value) proto.RegisterEnum("opentelemetry.proto.logs.v1.LogRecordFlags", LogRecordFlags_name, LogRecordFlags_value) @@ -539,67 +561,68 @@ func init() { } var fileDescriptor_d1c030a3ec7e961e = []byte{ - // 951 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x96, 0xcf, 0x6e, 0xea, 0x46, - 0x14, 0xc6, 0x31, 0xe1, 0xef, 0x84, 0x70, 0xa7, 0x73, 0x49, 0xae, 0x9b, 0xa8, 0x84, 0xa6, 0x55, - 0x4a, 0x53, 0x09, 0x14, 0xa0, 0xd2, 0xed, 0xae, 0x26, 0x98, 0x88, 0x86, 0x40, 0x34, 0x40, 0xaa, - 0xdc, 0x56, 0xb2, 0x0c, 0x9e, 0x52, 0x4b, 0xc6, 0x63, 0xd9, 0x03, 0x4a, 0xf6, 0x7d, 0x80, 0x3e, - 0x41, 0xb7, 0x95, 0xfa, 0x1a, 0xed, 0xe2, 0x2e, 0xef, 0xb2, 0xea, 0x22, 0xaa, 0x92, 0x4d, 0xdf, - 0xa2, 0xd5, 0x0c, 0x86, 0x90, 0xd4, 0x4e, 0x6e, 0x56, 0x99, 0x39, 0xbf, 0xef, 0x7c, 0xe7, 0x8c, - 0x4f, 0x3c, 0x18, 0xec, 0x53, 0x87, 0xd8, 0x8c, 0x58, 0x64, 0x42, 0x98, 0x7b, 0x55, 0x76, 0x5c, - 0xca, 0x68, 0xd9, 0xa2, 0x63, 0xaf, 0x3c, 0x3b, 0x14, 0x7f, 0x4b, 0x22, 0x84, 0x76, 0xee, 0xe9, - 0xe6, 0xc1, 0x92, 0xe0, 0xb3, 0xc3, 0xed, 0xdc, 0x98, 0x8e, 0xe9, 0x3c, 0x95, 0xaf, 0xe6, 0x74, - 0xfb, 0x20, 0xc8, 0x7a, 0x44, 0x27, 0x13, 0x6a, 0x73, 0xf3, 0xf9, 0xca, 0xd7, 0x96, 0x82, 0xb4, - 0x2e, 0xf1, 0xe8, 0xd4, 0x1d, 0x11, 0xae, 0x5e, 0xac, 0xe7, 0xfa, 0xbd, 0x37, 0x20, 0xd5, 0xa6, - 0x63, 0xaf, 0xa1, 0x33, 0x1d, 0x75, 0xc0, 0xc6, 0x82, 0x6a, 0xbc, 0x23, 0x59, 0x2a, 0xac, 0x15, - 0xd7, 0x2b, 0x9f, 0x97, 0x1e, 0x69, 0xb9, 0x84, 0xfd, 0x0c, 0xee, 0x82, 0x33, 0xee, 0xca, 0x6e, - 0xef, 0x97, 0x28, 0xc8, 0xac, 0x62, 0xf4, 0x1d, 0xd8, 0x34, 0x88, 0xe3, 0x92, 0x91, 0xce, 0x88, - 0xa1, 0x79, 0x23, 0xea, 0xf8, 0x85, 0xfe, 0x49, 0x8a, 0x4a, 0xfb, 0x8f, 0x56, 0xea, 0x71, 0xbd, - 0x28, 0xf3, 0xf2, 0xce, 0x65, 0x19, 0x44, 0x27, 0x20, 0xb5, 0xa8, 0x2e, 0x4b, 0x05, 0x29, 0xb4, - 0xf1, 0xe5, 0x03, 0x58, 0x69, 0xbe, 0x1e, 0x7b, 0x7b, 0xbd, 0x1b, 0xc1, 0x4b, 0x03, 0xa4, 0x02, - 0xb0, 0xd2, 0x5e, 0xf4, 0x59, 0xdd, 0xa5, 0xbd, 0x65, 0x4f, 0x1f, 0x71, 0x9b, 0x1f, 0xc9, 0x44, - 0xd7, 0xa6, 0xae, 0x25, 0xaf, 0x15, 0xa4, 0x62, 0x9a, 0x63, 0x1e, 0x19, 0xb8, 0xd6, 0xde, 0x1f, - 0x12, 0x48, 0xdf, 0x1d, 0xa0, 0x0b, 0xe2, 0x22, 0xd3, 0xef, 0xbe, 0x1a, 0x58, 0xce, 0x1f, 0xf6, - 0xec, 0xb0, 0xd4, 0xb2, 0x3d, 0xe6, 0x4e, 0x27, 0xc4, 0x66, 0x3a, 0x33, 0xa9, 0x2d, 0x7c, 0xfc, - 0x73, 0xcc, 0x7d, 0xd0, 0x31, 0x58, 0xb7, 0xe8, 0x58, 0x73, 0xc9, 0x88, 0xba, 0xc6, 0xfb, 0x9d, - 0xa2, 0x4d, 0xc7, 0x58, 0xc8, 0x31, 0xb0, 0x16, 0xcb, 0x27, 0x8f, 0xf1, 0x53, 0x1c, 0xa4, 0x97, - 0x89, 0xe8, 0x53, 0x90, 0x65, 0xe6, 0x84, 0x68, 0x53, 0xdb, 0xbc, 0xd4, 0x6c, 0xdd, 0xa6, 0xe2, - 0x3c, 0x09, 0x9c, 0xe1, 0xd1, 0x81, 0x6d, 0x5e, 0x76, 0x74, 0x9b, 0xa2, 0x2f, 0xc1, 0x2b, 0x3a, - 0xf4, 0x88, 0x3b, 0x23, 0x86, 0xf6, 0x40, 0xbe, 0x2e, 0xe4, 0xb9, 0x05, 0xee, 0xaf, 0xa6, 0xf5, - 0xc1, 0x0b, 0x8f, 0xcc, 0x88, 0x6b, 0xb2, 0x2b, 0xcd, 0x9e, 0x4e, 0x86, 0xc4, 0x95, 0xa3, 0x05, - 0xa9, 0x98, 0xad, 0x7c, 0xf1, 0xf8, 0x70, 0xfc, 0x9c, 0x8e, 0x48, 0xc1, 0x59, 0xef, 0xde, 0x1e, - 0x7d, 0x02, 0x36, 0x96, 0xae, 0x8c, 0x5c, 0x32, 0xff, 0x88, 0x99, 0x45, 0xb0, 0x4f, 0x2e, 0x19, - 0x52, 0x40, 0x6c, 0x48, 0x8d, 0x2b, 0x39, 0x2e, 0xa6, 0xf3, 0xd9, 0x13, 0xd3, 0x51, 0xec, 0xab, - 0x73, 0xdd, 0x9a, 0x2e, 0x26, 0x22, 0x52, 0xd1, 0x29, 0x00, 0x3a, 0x63, 0xae, 0x39, 0x9c, 0x32, - 0xe2, 0xc9, 0x09, 0x31, 0x8f, 0xa7, 0x8c, 0x4e, 0xc8, 0x3d, 0xa3, 0x15, 0x03, 0xf4, 0x1a, 0xc8, - 0x86, 0x4b, 0x1d, 0x87, 0x18, 0xda, 0x5d, 0x54, 0x1b, 0xd1, 0xa9, 0xcd, 0xe4, 0x64, 0x41, 0x2a, - 0x6e, 0xe0, 0x2d, 0x9f, 0x2b, 0x4b, 0x7c, 0xc4, 0x29, 0xca, 0x81, 0xf8, 0x0f, 0x96, 0x3e, 0xf6, - 0xe4, 0x54, 0x41, 0x2a, 0x26, 0xf1, 0x7c, 0x83, 0xbe, 0x07, 0x29, 0xe6, 0xea, 0x23, 0xa2, 0x99, - 0x86, 0x9c, 0x2e, 0x48, 0xc5, 0x4c, 0x5d, 0xe1, 0x35, 0xff, 0xba, 0xde, 0xfd, 0x6a, 0x4c, 0x1f, - 0xb4, 0x69, 0xf2, 0x1b, 0xc8, 0xb2, 0xc8, 0x88, 0x51, 0xb7, 0xec, 0x18, 0x3a, 0xd3, 0xcb, 0xa6, - 0xcd, 0x88, 0x6b, 0xeb, 0x56, 0x99, 0xef, 0x4a, 0x7d, 0xee, 0xd4, 0x6a, 0xe0, 0xa4, 0xb0, 0x6c, - 0x19, 0xe8, 0x02, 0x24, 0x3d, 0x47, 0xb7, 0xb9, 0x39, 0x10, 0xe6, 0x5f, 0xfb, 0xe6, 0xaf, 0x9f, - 0x6f, 0xde, 0x73, 0x74, 0xbb, 0xd5, 0xc0, 0x09, 0x6e, 0xd8, 0x32, 0xbe, 0x89, 0xa5, 0x62, 0x30, - 0x7e, 0xf0, 0x7b, 0x1c, 0x64, 0xef, 0x0f, 0x1a, 0xed, 0x82, 0x9d, 0x9e, 0x7a, 0xae, 0xe2, 0x56, - 0xff, 0x42, 0xeb, 0x0c, 0x4e, 0xeb, 0x2a, 0xd6, 0x06, 0x9d, 0xde, 0x99, 0x7a, 0xd4, 0x6a, 0xb6, - 0xd4, 0x06, 0x8c, 0xa0, 0x0f, 0xc1, 0xe6, 0x43, 0x41, 0x1f, 0x2b, 0x47, 0x2a, 0x94, 0xd0, 0x36, - 0xd8, 0x0a, 0x44, 0x15, 0x18, 0x0d, 0x65, 0x55, 0xb8, 0x16, 0xca, 0x6a, 0x30, 0x16, 0x54, 0xae, - 0xa1, 0xd6, 0x07, 0xc7, 0x30, 0x1e, 0x94, 0x26, 0x50, 0x05, 0x26, 0x42, 0x59, 0x15, 0x26, 0x43, - 0x59, 0x0d, 0xa6, 0x90, 0x0c, 0x72, 0x0f, 0x59, 0xab, 0xd3, 0xec, 0xc2, 0x74, 0x50, 0x23, 0x9c, - 0x54, 0x20, 0x08, 0x43, 0x55, 0xb8, 0x1e, 0x86, 0x6a, 0x30, 0x13, 0x54, 0xea, 0x5b, 0x05, 0x77, - 0xe0, 0x46, 0x50, 0x12, 0x27, 0x15, 0x98, 0x0d, 0x43, 0x55, 0xf8, 0x22, 0x0c, 0xd5, 0x20, 0x0c, - 0x42, 0x2a, 0xc6, 0x5d, 0x0c, 0x3f, 0x08, 0x7a, 0x18, 0x02, 0x55, 0x20, 0x0a, 0x65, 0x55, 0xf8, - 0x32, 0x94, 0xd5, 0x60, 0x2e, 0xa8, 0x5c, 0x53, 0xe9, 0x2b, 0x6d, 0xb8, 0x19, 0x94, 0x26, 0x50, - 0x05, 0x6e, 0x85, 0xb2, 0x2a, 0x7c, 0x15, 0xca, 0x6a, 0x50, 0x3e, 0xb8, 0x00, 0xd9, 0xe5, 0x5d, - 0xda, 0x14, 0xaf, 0xe5, 0x2e, 0xd8, 0x69, 0x77, 0x8f, 0x35, 0xac, 0x1e, 0x75, 0x71, 0x43, 0x6b, - 0xb6, 0x95, 0xe3, 0x9e, 0xd6, 0xe8, 0x6a, 0x9d, 0x6e, 0x5f, 0x1b, 0xf4, 0x54, 0x18, 0x41, 0xfb, - 0xe0, 0xe3, 0xff, 0x09, 0xc4, 0xbf, 0x9c, 0xbf, 0x3e, 0x55, 0x7a, 0x27, 0xf0, 0x5f, 0xa9, 0xfe, - 0xab, 0xf4, 0xf6, 0x26, 0x2f, 0xbd, 0xbb, 0xc9, 0x4b, 0x7f, 0xdf, 0xe4, 0xa5, 0x9f, 0x6f, 0xf3, - 0x91, 0x77, 0xb7, 0xf9, 0xc8, 0x9f, 0xb7, 0xf9, 0x08, 0xc8, 0x9b, 0xf4, 0xb1, 0x0b, 0xb4, 0xce, - 0xef, 0x77, 0xef, 0x8c, 0x87, 0xce, 0xa4, 0x37, 0xf5, 0x67, 0xbf, 0xb0, 0xf3, 0xef, 0x90, 0x31, - 0xb1, 0x17, 0x5f, 0x44, 0xbf, 0x45, 0x77, 0xba, 0x0e, 0xb1, 0xfb, 0x4b, 0x07, 0xe1, 0xcd, 0x7f, - 0x7e, 0xbc, 0xd2, 0xf9, 0xe1, 0x30, 0x21, 0xf4, 0xd5, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x48, - 0x86, 0x67, 0x14, 0x55, 0x09, 0x00, 0x00, + // 971 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x96, 0x41, 0x6f, 0xe2, 0x46, + 0x1b, 0xc7, 0x71, 0x12, 0x02, 0x4c, 0x08, 0x3b, 0xef, 0x2c, 0xc9, 0xfa, 0x4d, 0x54, 0x42, 0xd3, + 0x2a, 0xa5, 0xa9, 0x04, 0x0a, 0x50, 0x69, 0x7b, 0xab, 0x09, 0x26, 0xa2, 0x21, 0x10, 0x0d, 0x90, + 0x2a, 0xdb, 0x4a, 0x96, 0xc1, 0x53, 0x6a, 0xc9, 0xcc, 0x58, 0xf6, 0x80, 0x92, 0x6f, 0xd1, 0x4f, + 0xd0, 0x4b, 0x0f, 0x95, 0xfa, 0x35, 0xda, 0xc3, 0x1e, 0xf7, 0x58, 0xf5, 0xb0, 0xaa, 0x92, 0x4b, + 0xbf, 0x45, 0xab, 0x19, 0x0c, 0x21, 0xa9, 0x9d, 0x34, 0x27, 0x66, 0x9e, 0xdf, 0xff, 0xf9, 0x3f, + 0xcf, 0x78, 0xc6, 0x83, 0xc1, 0x01, 0x73, 0x09, 0xe5, 0xc4, 0x21, 0x63, 0xc2, 0xbd, 0xeb, 0x92, + 0xeb, 0x31, 0xce, 0x4a, 0x0e, 0x1b, 0xf9, 0xa5, 0xe9, 0x91, 0xfc, 0x2d, 0xca, 0x10, 0xda, 0xbd, + 0xa7, 0x9b, 0x05, 0x8b, 0x92, 0x4f, 0x8f, 0x76, 0xb2, 0x23, 0x36, 0x62, 0xb3, 0x54, 0x31, 0x9a, + 0xd1, 0x9d, 0xc3, 0x30, 0xeb, 0x21, 0x1b, 0x8f, 0x19, 0x15, 0xe6, 0xb3, 0x51, 0xa0, 0x2d, 0x86, + 0x69, 0x3d, 0xe2, 0xb3, 0x89, 0x37, 0x24, 0x42, 0x3d, 0x1f, 0xcf, 0xf4, 0xfb, 0x6f, 0x40, 0xb2, + 0xc5, 0x46, 0x7e, 0xdd, 0xe4, 0x26, 0x6a, 0x83, 0xcd, 0x39, 0x35, 0x44, 0x47, 0xaa, 0x92, 0x5f, + 0x2d, 0x6c, 0x94, 0x3f, 0x2d, 0x3e, 0xd2, 0x72, 0x11, 0x07, 0x19, 0xc2, 0x05, 0xa7, 0xbd, 0xa5, + 0xd9, 0xfe, 0x8f, 0x2b, 0x20, 0xbd, 0x8c, 0xd1, 0x37, 0x60, 0xcb, 0x22, 0xae, 0x47, 0x86, 0x26, + 0x27, 0x96, 0xe1, 0x0f, 0x99, 0x1b, 0x14, 0xfa, 0x2b, 0x21, 0x2b, 0x1d, 0x3c, 0x5a, 0xa9, 0x2b, + 0xf4, 0xb2, 0xcc, 0xcb, 0x3b, 0x97, 0x45, 0x10, 0x9d, 0x82, 0xe4, 0xbc, 0xba, 0xaa, 0xe4, 0x95, + 0xc8, 0xc6, 0x17, 0x0f, 0x60, 0xa9, 0xf9, 0xda, 0xda, 0xdb, 0xf7, 0x7b, 0x31, 0xbc, 0x30, 0x40, + 0x3a, 0x00, 0x4b, 0xed, 0xad, 0x3c, 0xab, 0xbb, 0x94, 0xbf, 0xe8, 0xe9, 0x03, 0x61, 0xf3, 0x3d, + 0x19, 0x9b, 0xc6, 0xc4, 0x73, 0xd4, 0xd5, 0xbc, 0x52, 0x48, 0x09, 0x2c, 0x22, 0x7d, 0xcf, 0xd9, + 0xff, 0x4d, 0x01, 0xa9, 0xbb, 0x05, 0x74, 0x40, 0x5c, 0x66, 0x06, 0xdd, 0x57, 0x42, 0xcb, 0x05, + 0x9b, 0x3d, 0x3d, 0x2a, 0x36, 0xa9, 0xcf, 0xbd, 0xc9, 0x98, 0x50, 0x6e, 0x72, 0x9b, 0x51, 0xe9, + 0x13, 0xac, 0x63, 0xe6, 0x83, 0x4e, 0xc0, 0x86, 0xc3, 0x46, 0x86, 0x47, 0x86, 0xcc, 0xb3, 0xfe, + 0xdb, 0x2a, 0x5a, 0x6c, 0x84, 0xa5, 0x1c, 0x03, 0x67, 0x3e, 0x7c, 0x72, 0x19, 0x3f, 0xc5, 0x41, + 0x6a, 0x91, 0x88, 0x3e, 0x06, 0x19, 0x6e, 0x8f, 0x89, 0x31, 0xa1, 0xf6, 0x95, 0x41, 0x4d, 0xca, + 0xe4, 0x7a, 0xd6, 0x71, 0x5a, 0x44, 0xfb, 0xd4, 0xbe, 0x6a, 0x9b, 0x94, 0xa1, 0xcf, 0xc1, 0x2b, + 0x36, 0xf0, 0x89, 0x37, 0x25, 0x96, 0xf1, 0x40, 0xbe, 0x21, 0xe5, 0xd9, 0x39, 0xee, 0x2d, 0xa7, + 0xf5, 0xc0, 0x0b, 0x9f, 0x4c, 0x89, 0x67, 0xf3, 0x6b, 0x83, 0x4e, 0xc6, 0x03, 0xe2, 0xa9, 0x2b, + 0x79, 0xa5, 0x90, 0x29, 0x7f, 0xf6, 0xf8, 0xe6, 0x04, 0x39, 0x6d, 0x99, 0x82, 0x33, 0xfe, 0xbd, + 0x39, 0xfa, 0x08, 0x6c, 0x2e, 0x5c, 0x39, 0xb9, 0xe2, 0xc1, 0x12, 0xd3, 0xf3, 0x60, 0x8f, 0x5c, + 0x71, 0xa4, 0x81, 0xb5, 0x01, 0xb3, 0xae, 0xd5, 0xb8, 0xdc, 0x9d, 0x4f, 0x9e, 0xd8, 0x1d, 0x8d, + 0x5e, 0x5f, 0x98, 0xce, 0x64, 0xbe, 0x23, 0x32, 0x15, 0x9d, 0x01, 0x60, 0x72, 0xee, 0xd9, 0x83, + 0x09, 0x27, 0xbe, 0xba, 0x2e, 0xf7, 0xe3, 0x29, 0xa3, 0x53, 0x72, 0xcf, 0x68, 0xc9, 0x00, 0xbd, + 0x06, 0xaa, 0xe5, 0x31, 0xd7, 0x25, 0x96, 0x71, 0x17, 0x35, 0x86, 0x6c, 0x42, 0xb9, 0x9a, 0xc8, + 0x2b, 0x85, 0x4d, 0xbc, 0x1d, 0x70, 0x6d, 0x81, 0x8f, 0x05, 0x45, 0x59, 0x10, 0xff, 0xce, 0x31, + 0x47, 0xbe, 0x9a, 0xcc, 0x2b, 0x85, 0x04, 0x9e, 0x4d, 0xd0, 0xb7, 0x20, 0xc9, 0x3d, 0x73, 0x48, + 0x0c, 0xdb, 0x52, 0x53, 0x79, 0xa5, 0x90, 0xae, 0x69, 0xa2, 0xe6, 0x1f, 0xef, 0xf7, 0xbe, 0x18, + 0xb1, 0x07, 0x6d, 0xda, 0xe2, 0x06, 0x72, 0x1c, 0x32, 0xe4, 0xcc, 0x2b, 0xb9, 0x96, 0xc9, 0xcd, + 0x92, 0x4d, 0x39, 0xf1, 0xa8, 0xe9, 0x94, 0xc4, 0xac, 0xd8, 0x13, 0x4e, 0xcd, 0x3a, 0x4e, 0x48, + 0xcb, 0xa6, 0x85, 0x2e, 0x41, 0xc2, 0x77, 0x4d, 0x2a, 0xcc, 0x81, 0x34, 0xff, 0x32, 0x30, 0x7f, + 0xfd, 0x7c, 0xf3, 0xae, 0x6b, 0xd2, 0x66, 0x1d, 0xaf, 0x0b, 0xc3, 0xa6, 0x25, 0xce, 0x27, 0x99, + 0x12, 0xca, 0x0d, 0x6a, 0x8e, 0x89, 0x9a, 0x9e, 0x9d, 0x4f, 0x19, 0x69, 0x9b, 0x63, 0xf2, 0xd5, + 0x5a, 0x72, 0x0d, 0xc6, 0x0f, 0x7f, 0x8d, 0x83, 0xcc, 0xfd, 0x73, 0x80, 0xf6, 0xc0, 0x6e, 0x57, + 0xbf, 0xd0, 0x71, 0xb3, 0x77, 0x69, 0xb4, 0xfb, 0x67, 0x35, 0x1d, 0x1b, 0xfd, 0x76, 0xf7, 0x5c, + 0x3f, 0x6e, 0x36, 0x9a, 0x7a, 0x1d, 0xc6, 0xd0, 0xff, 0xc1, 0xd6, 0x43, 0x41, 0x0f, 0x6b, 0xc7, + 0x3a, 0x54, 0xd0, 0x0e, 0xd8, 0x0e, 0x45, 0x65, 0xb8, 0x12, 0xc9, 0x2a, 0x70, 0x35, 0x92, 0x55, + 0xe1, 0x5a, 0x58, 0xb9, 0xba, 0x5e, 0xeb, 0x9f, 0xc0, 0x78, 0x58, 0x9a, 0x44, 0x65, 0xb8, 0x1e, + 0xc9, 0x2a, 0x30, 0x11, 0xc9, 0xaa, 0x30, 0x89, 0x54, 0x90, 0x7d, 0xc8, 0x9a, 0xed, 0x46, 0x07, + 0xa6, 0xc2, 0x1a, 0x11, 0xa4, 0x0c, 0x41, 0x14, 0xaa, 0xc0, 0x8d, 0x28, 0x54, 0x85, 0xe9, 0xb0, + 0x52, 0x5f, 0x6b, 0xb8, 0x0d, 0x37, 0xc3, 0x92, 0x04, 0x29, 0xc3, 0x4c, 0x14, 0xaa, 0xc0, 0x17, + 0x51, 0xa8, 0x0a, 0x61, 0x18, 0xd2, 0x31, 0xee, 0x60, 0xf8, 0xbf, 0xb0, 0x87, 0x21, 0x51, 0x19, + 0xa2, 0x48, 0x56, 0x81, 0x2f, 0x23, 0x59, 0x15, 0x66, 0xc3, 0xca, 0x35, 0xb4, 0x9e, 0xd6, 0x82, + 0x5b, 0x61, 0x69, 0x12, 0x95, 0xe1, 0x76, 0x24, 0xab, 0xc0, 0x57, 0x91, 0xac, 0x0a, 0xd5, 0xc3, + 0x4b, 0x90, 0x59, 0x5c, 0xb5, 0x0d, 0xf9, 0xd6, 0xee, 0x81, 0xdd, 0x56, 0xe7, 0xc4, 0xc0, 0xfa, + 0x71, 0x07, 0xd7, 0x8d, 0x46, 0x4b, 0x3b, 0xe9, 0x1a, 0xf5, 0x8e, 0xd1, 0xee, 0xf4, 0x8c, 0x7e, + 0x57, 0x87, 0x31, 0x74, 0x00, 0x3e, 0xfc, 0x97, 0x40, 0x1e, 0xb9, 0x60, 0x7c, 0xa6, 0x75, 0x4f, + 0xe1, 0xdf, 0x4a, 0xed, 0x67, 0xe5, 0xed, 0x4d, 0x4e, 0x79, 0x77, 0x93, 0x53, 0xfe, 0xbc, 0xc9, + 0x29, 0x3f, 0xdc, 0xe6, 0x62, 0xef, 0x6e, 0x73, 0xb1, 0xdf, 0x6f, 0x73, 0x31, 0x90, 0xb3, 0xd9, + 0x63, 0xf7, 0x6b, 0x4d, 0x5c, 0xff, 0xfe, 0xb9, 0x08, 0x9d, 0x2b, 0x6f, 0x6a, 0xcf, 0x7e, 0x9f, + 0x67, 0x9f, 0x29, 0x23, 0x42, 0xe7, 0x1f, 0x4c, 0xbf, 0xac, 0xec, 0x76, 0x5c, 0x42, 0x7b, 0x0b, + 0x07, 0xe9, 0x2d, 0xfe, 0x9d, 0xfc, 0xe2, 0xc5, 0xd1, 0x60, 0x5d, 0xea, 0x2b, 0xff, 0x04, 0x00, + 0x00, 0xff, 0xff, 0xc9, 0xbc, 0x36, 0x44, 0x74, 0x09, 0x00, 0x00, } func (m *LogsData) Marshal() (dAtA []byte, err error) { @@ -783,6 +806,13 @@ func (m *LogRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.EventName) > 0 { + i -= len(m.EventName) + copy(dAtA[i:], m.EventName) + i = encodeVarintLogs(dAtA, i, uint64(len(m.EventName))) + i-- + dAtA[i] = 0x62 + } if m.ObservedTimeUnixNano != 0 { i -= 8 encoding_binary.LittleEndian.PutUint64(dAtA[i:], uint64(m.ObservedTimeUnixNano)) @@ -976,6 +1006,10 @@ func (m *LogRecord) Size() (n int) { if m.ObservedTimeUnixNano != 0 { n += 9 } + l = len(m.EventName) + if l > 0 { + n += 1 + l + sovLogs(uint64(l)) + } return n } @@ -1663,6 +1697,38 @@ func (m *LogRecord) Unmarshal(dAtA []byte) error { } m.ObservedTimeUnixNano = uint64(encoding_binary.LittleEndian.Uint64(dAtA[iNdEx:])) iNdEx += 8 + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field EventName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowLogs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthLogs + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthLogs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.EventName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipLogs(dAtA[iNdEx:]) diff --git a/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1/metrics.pb.go b/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1/metrics.pb.go index 6614333796..9021e432c5 100644 --- a/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1/metrics.pb.go +++ b/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1/metrics.pb.go @@ -243,7 +243,8 @@ type ResourceMetrics struct { // A list of metrics that originate from a resource. ScopeMetrics []*ScopeMetrics `protobuf:"bytes,2,rep,name=scope_metrics,json=scopeMetrics,proto3" json:"scope_metrics,omitempty"` // The Schema URL, if known. This is the identifier of the Schema that the resource data - // is recorded in. To learn more about Schema URL see + // is recorded in. Notably, the last part of the URL path is the version number of the + // schema: http[s]://server[:port]/path/. To learn more about Schema URL see // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to the data in the "resource" field. It does not apply // to the data in the "scope_metrics" field which have their own schema_url field. @@ -320,7 +321,8 @@ type ScopeMetrics struct { // A list of metrics that originate from an instrumentation library. Metrics []*Metric `protobuf:"bytes,2,rep,name=metrics,proto3" json:"metrics,omitempty"` // The Schema URL, if known. This is the identifier of the Schema that the metric data - // is recorded in. To learn more about Schema URL see + // is recorded in. Notably, the last part of the URL path is the version number of the + // schema: http[s]://server[:port]/path/. To learn more about Schema URL see // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to all metrics in the "metrics" field. SchemaUrl string `protobuf:"bytes,3,opt,name=schema_url,json=schemaUrl,proto3" json:"schema_url,omitempty"` @@ -1106,7 +1108,7 @@ type HistogramDataPoint struct { // events, and is assumed to be monotonic over the values of these events. // Negative events *can* be recorded, but sum should not be filled out when // doing so. This is specifically to enforce compatibility w/ OpenMetrics, - // see: https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#histogram + // see: https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#histogram // // Types that are valid to be assigned to Sum_: // *HistogramDataPoint_Sum @@ -1351,7 +1353,7 @@ type ExponentialHistogramDataPoint struct { // events, and is assumed to be monotonic over the values of these events. // Negative events *can* be recorded, but sum should not be filled out when // doing so. This is specifically to enforce compatibility w/ OpenMetrics, - // see: https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#histogram + // see: https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#histogram // // Types that are valid to be assigned to Sum_: // *ExponentialHistogramDataPoint_Sum @@ -1694,7 +1696,7 @@ type SummaryDataPoint struct { // events, and is assumed to be monotonic over the values of these events. // Negative events *can* be recorded, but sum should not be filled out when // doing so. This is specifically to enforce compatibility w/ OpenMetrics, - // see: https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#summary + // see: https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#summary Sum float64 `protobuf:"fixed64,5,opt,name=sum,proto3" json:"sum,omitempty"` // (Optional) list of values at different quantiles of the distribution calculated // from the current snapshot. The quantiles must be strictly increasing. diff --git a/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development/profiles.pb.go b/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development/profiles.pb.go index faa8630469..bafc9d85f0 100644 --- a/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development/profiles.pb.go +++ b/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development/profiles.pb.go @@ -183,7 +183,8 @@ type ResourceProfiles struct { // A list of ScopeProfiles that originate from a resource. ScopeProfiles []*ScopeProfiles `protobuf:"bytes,2,rep,name=scope_profiles,json=scopeProfiles,proto3" json:"scope_profiles,omitempty"` // The Schema URL, if known. This is the identifier of the Schema that the resource data - // is recorded in. To learn more about Schema URL see + // is recorded in. Notably, the last part of the URL path is the version number of the + // schema: http[s]://server[:port]/path/. To learn more about Schema URL see // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to the data in the "resource" field. It does not apply // to the data in the "scope_profiles" field which have their own schema_url field. @@ -253,7 +254,8 @@ type ScopeProfiles struct { // A list of Profiles that originate from an instrumentation scope. Profiles []*Profile `protobuf:"bytes,2,rep,name=profiles,proto3" json:"profiles,omitempty"` // The Schema URL, if known. This is the identifier of the Schema that the profile data - // is recorded in. To learn more about Schema URL see + // is recorded in. Notably, the last part of the URL path is the version number of the + // schema: http[s]://server[:port]/path/. To learn more about Schema URL see // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to all profiles in the "profiles" field. SchemaUrl string `protobuf:"bytes,3,opt,name=schema_url,json=schemaUrl,proto3" json:"schema_url,omitempty"` @@ -375,19 +377,6 @@ type Profile struct { // // This field is required. ProfileId go_opentelemetry_io_collector_pdata_internal_data.ProfileID `protobuf:"bytes,17,opt,name=profile_id,json=profileId,proto3,customtype=go.opentelemetry.io/collector/pdata/internal/data.ProfileID" json:"profile_id"` - // attributes is a collection of key/value pairs. Note, global attributes - // like server name can be set using the resource API. Examples of attributes: - // - // "/http/user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36" - // "/http/server_latency": 300 - // "abc.com/myattribute": true - // "abc.com/score": 10.239 - // - // The OpenTelemetry API specification further restricts the allowed value types: - // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/common/README.md#attribute - // Attribute keys MUST be unique (it is not allowed to have more than one - // attribute with the same key). - Attributes []v11.KeyValue `protobuf:"bytes,18,rep,name=attributes,proto3" json:"attributes"` // dropped_attributes_count is the number of attributes that were discarded. Attributes // can be discarded because their keys are too long or because there are too many // attributes. If this value is 0, then no attributes were dropped. @@ -401,6 +390,20 @@ type Profile struct { // The field is optional, however if it is present then equivalent converted data should be populated in other fields // of this message as far as is practicable. OriginalPayload []byte `protobuf:"bytes,21,opt,name=original_payload,json=originalPayload,proto3" json:"original_payload,omitempty"` + // References to attributes in attribute_table. [optional] + // It is a collection of key/value pairs. Note, global attributes + // like server name can be set using the resource API. Examples of attributes: + // + // "/http/user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36" + // "/http/server_latency": 300 + // "abc.com/myattribute": true + // "abc.com/score": 10.239 + // + // The OpenTelemetry API specification further restricts the allowed value types: + // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/common/README.md#attribute + // Attribute keys MUST be unique (it is not allowed to have more than one + // attribute with the same key). + AttributeIndices []int32 `protobuf:"varint,22,rep,packed,name=attribute_indices,json=attributeIndices,proto3" json:"attribute_indices,omitempty"` } func (m *Profile) Reset() { *m = Profile{} } @@ -548,13 +551,6 @@ func (m *Profile) GetDefaultSampleTypeStrindex() int32 { return 0 } -func (m *Profile) GetAttributes() []v11.KeyValue { - if m != nil { - return m.Attributes - } - return nil -} - func (m *Profile) GetDroppedAttributesCount() uint32 { if m != nil { return m.DroppedAttributesCount @@ -576,6 +572,13 @@ func (m *Profile) GetOriginalPayload() []byte { return nil } +func (m *Profile) GetAttributeIndices() []int32 { + if m != nil { + return m.AttributeIndices + } + return nil +} + // Represents a mapping between Attribute Keys and Units. type AttributeUnit struct { // Index into string table. @@ -865,84 +868,6 @@ func (*Sample) XXX_OneofWrappers() []interface{} { } } -// Provides additional context for a sample, -// such as thread ID or allocation size, with optional units. [deprecated] -type Label struct { - KeyStrindex int32 `protobuf:"varint,1,opt,name=key_strindex,json=keyStrindex,proto3" json:"key_strindex,omitempty"` - // At most one of the following must be present - StrStrindex int32 `protobuf:"varint,2,opt,name=str_strindex,json=strStrindex,proto3" json:"str_strindex,omitempty"` - Num int64 `protobuf:"varint,3,opt,name=num,proto3" json:"num,omitempty"` - // Should only be present when num is present. - // Specifies the units of num. - // Use arbitrary string (for example, "requests") as a custom count unit. - // If no unit is specified, consumer may apply heuristic to deduce the unit. - // Consumers may also interpret units like "bytes" and "kilobytes" as memory - // units and units like "seconds" and "nanoseconds" as time units, - // and apply appropriate unit conversions to these. - NumUnitStrindex int32 `protobuf:"varint,4,opt,name=num_unit_strindex,json=numUnitStrindex,proto3" json:"num_unit_strindex,omitempty"` -} - -func (m *Label) Reset() { *m = Label{} } -func (m *Label) String() string { return proto.CompactTextString(m) } -func (*Label) ProtoMessage() {} -func (*Label) Descriptor() ([]byte, []int) { - return fileDescriptor_ddd0cf081a2fe76f, []int{8} -} -func (m *Label) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *Label) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Label.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *Label) XXX_Merge(src proto.Message) { - xxx_messageInfo_Label.Merge(m, src) -} -func (m *Label) XXX_Size() int { - return m.Size() -} -func (m *Label) XXX_DiscardUnknown() { - xxx_messageInfo_Label.DiscardUnknown(m) -} - -var xxx_messageInfo_Label proto.InternalMessageInfo - -func (m *Label) GetKeyStrindex() int32 { - if m != nil { - return m.KeyStrindex - } - return 0 -} - -func (m *Label) GetStrStrindex() int32 { - if m != nil { - return m.StrStrindex - } - return 0 -} - -func (m *Label) GetNum() int64 { - if m != nil { - return m.Num - } - return 0 -} - -func (m *Label) GetNumUnitStrindex() int32 { - if m != nil { - return m.NumUnitStrindex - } - return 0 -} - // Describes the mapping of a binary in memory, including its address range, // file offset, and metadata like build ID type Mapping struct { @@ -969,7 +894,7 @@ func (m *Mapping) Reset() { *m = Mapping{} } func (m *Mapping) String() string { return proto.CompactTextString(m) } func (*Mapping) ProtoMessage() {} func (*Mapping) Descriptor() ([]byte, []int) { - return fileDescriptor_ddd0cf081a2fe76f, []int{9} + return fileDescriptor_ddd0cf081a2fe76f, []int{8} } func (m *Mapping) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1098,7 +1023,7 @@ func (m *Location) Reset() { *m = Location{} } func (m *Location) String() string { return proto.CompactTextString(m) } func (*Location) ProtoMessage() {} func (*Location) Descriptor() ([]byte, []int) { - return fileDescriptor_ddd0cf081a2fe76f, []int{10} + return fileDescriptor_ddd0cf081a2fe76f, []int{9} } func (m *Location) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1202,7 +1127,7 @@ func (m *Line) Reset() { *m = Line{} } func (m *Line) String() string { return proto.CompactTextString(m) } func (*Line) ProtoMessage() {} func (*Line) Descriptor() ([]byte, []int) { - return fileDescriptor_ddd0cf081a2fe76f, []int{11} + return fileDescriptor_ddd0cf081a2fe76f, []int{10} } func (m *Line) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1270,7 +1195,7 @@ func (m *Function) Reset() { *m = Function{} } func (m *Function) String() string { return proto.CompactTextString(m) } func (*Function) ProtoMessage() {} func (*Function) Descriptor() ([]byte, []int) { - return fileDescriptor_ddd0cf081a2fe76f, []int{12} + return fileDescriptor_ddd0cf081a2fe76f, []int{11} } func (m *Function) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1337,7 +1262,6 @@ func init() { proto.RegisterType((*Link)(nil), "opentelemetry.proto.profiles.v1development.Link") proto.RegisterType((*ValueType)(nil), "opentelemetry.proto.profiles.v1development.ValueType") proto.RegisterType((*Sample)(nil), "opentelemetry.proto.profiles.v1development.Sample") - proto.RegisterType((*Label)(nil), "opentelemetry.proto.profiles.v1development.Label") proto.RegisterType((*Mapping)(nil), "opentelemetry.proto.profiles.v1development.Mapping") proto.RegisterType((*Location)(nil), "opentelemetry.proto.profiles.v1development.Location") proto.RegisterType((*Line)(nil), "opentelemetry.proto.profiles.v1development.Line") @@ -1349,110 +1273,107 @@ func init() { } var fileDescriptor_ddd0cf081a2fe76f = []byte{ - // 1647 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x58, 0x5b, 0x6f, 0x1b, 0xc7, - 0x15, 0xd6, 0xf2, 0xce, 0xc3, 0x8b, 0xa8, 0x89, 0xac, 0x6c, 0xd3, 0x5a, 0x66, 0x68, 0xa4, 0x61, - 0x54, 0x44, 0xb2, 0xe4, 0xb4, 0x88, 0xd1, 0x02, 0xad, 0x64, 0x4a, 0x0e, 0x63, 0xea, 0xd2, 0x15, - 0x25, 0xd4, 0x6d, 0x80, 0xed, 0x88, 0x3b, 0xa4, 0xb6, 0xda, 0x9d, 0x5d, 0xec, 0x0c, 0x05, 0x13, - 0xfd, 0x09, 0xcd, 0x43, 0x1f, 0xfb, 0x1b, 0x0a, 0xf4, 0x37, 0xf4, 0x35, 0x8f, 0x46, 0x9f, 0x82, - 0x3e, 0x04, 0x85, 0xfd, 0x92, 0x16, 0xe8, 0x7f, 0x28, 0xe6, 0xb2, 0xcb, 0x4b, 0x29, 0x24, 0xeb, - 0x17, 0x61, 0xe7, 0x9c, 0x6f, 0xbe, 0x39, 0x67, 0xce, 0x65, 0x8e, 0x08, 0x4f, 0x82, 0x90, 0x50, - 0x4e, 0x3c, 0xe2, 0x13, 0x1e, 0x4d, 0x76, 0xc2, 0x28, 0xe0, 0x81, 0xf8, 0x3b, 0x74, 0x3d, 0xc2, - 0x76, 0x6e, 0x77, 0x1d, 0x72, 0x4b, 0xbc, 0x20, 0xf4, 0x09, 0xe5, 0x89, 0x78, 0x5b, 0xa2, 0xd0, - 0xd6, 0xdc, 0x56, 0x25, 0xdc, 0x4e, 0x30, 0x73, 0x5b, 0xdf, 0x5b, 0x1f, 0x05, 0xa3, 0x40, 0x91, - 0x8b, 0x2f, 0x05, 0x7e, 0x6f, 0x6b, 0xd9, 0xe1, 0x83, 0xc0, 0xf7, 0x03, 0xba, 0x73, 0xbb, 0xab, - 0xbf, 0x34, 0x76, 0x7b, 0x19, 0x36, 0x22, 0x2c, 0x18, 0x47, 0x03, 0x22, 0xd0, 0xf1, 0xb7, 0xc2, - 0xb7, 0x26, 0x50, 0x3d, 0xd3, 0xb6, 0x74, 0x30, 0xc7, 0xc8, 0x85, 0xb5, 0x18, 0x61, 0xc7, 0x46, - 0x9a, 0x46, 0x33, 0xdb, 0xae, 0xec, 0xfd, 0x62, 0xfb, 0xfb, 0x7b, 0xb2, 0x6d, 0x69, 0x92, 0x98, - 0xdc, 0x6a, 0x44, 0x0b, 0x92, 0xd6, 0xb7, 0x06, 0x34, 0x16, 0x61, 0xe8, 0x39, 0x94, 0x62, 0xa0, - 0x69, 0x34, 0x8d, 0x76, 0x65, 0xef, 0xa3, 0xa5, 0xc7, 0x26, 0x6e, 0xdc, 0xee, 0x26, 0x67, 0x1d, - 0xe4, 0xbe, 0xfa, 0xe6, 0xc1, 0x8a, 0x95, 0x10, 0xa0, 0xdf, 0x43, 0x9d, 0x0d, 0x82, 0x70, 0xc6, - 0x93, 0x8c, 0xf4, 0xe4, 0x49, 0x1a, 0x4f, 0xce, 0x05, 0x43, 0xe2, 0x46, 0x8d, 0xcd, 0x2e, 0xd1, - 0x7d, 0x00, 0x36, 0xb8, 0x26, 0x3e, 0xb6, 0xc7, 0x91, 0x67, 0x66, 0x9b, 0x46, 0xbb, 0x6c, 0x95, - 0x95, 0xe4, 0x22, 0xf2, 0x3e, 0x2f, 0x94, 0xbe, 0x2d, 0x36, 0xfe, 0x5d, 0x6c, 0xbd, 0x32, 0xa0, - 0x36, 0xc7, 0x83, 0x4e, 0x21, 0x2f, 0x99, 0xb4, 0x93, 0x8f, 0x97, 0x5a, 0xa4, 0x23, 0x7b, 0xbb, - 0xbb, 0xdd, 0xa5, 0x8c, 0x47, 0x63, 0x61, 0x0f, 0xe6, 0x6e, 0x40, 0x25, 0x97, 0x76, 0x57, 0xf1, - 0xa0, 0x53, 0x28, 0x2d, 0x78, 0xf9, 0x38, 0x8d, 0x97, 0xda, 0x30, 0x2b, 0x21, 0xf9, 0x0e, 0xd7, - 0x5a, 0x7f, 0xa9, 0x40, 0x51, 0x6f, 0x42, 0x97, 0x50, 0x61, 0xd8, 0x0f, 0x3d, 0x62, 0xf3, 0x89, - 0x74, 0x49, 0x1c, 0xff, 0xd3, 0x34, 0xc7, 0x5f, 0x62, 0x6f, 0x4c, 0xfa, 0x93, 0x90, 0x58, 0xa0, - 0x98, 0xc4, 0x37, 0xfa, 0x1c, 0x0a, 0x6a, 0xa5, 0x3d, 0xda, 0x4b, 0x15, 0x37, 0xb9, 0xd3, 0xd2, - 0x0c, 0xe8, 0x37, 0x50, 0xf3, 0x71, 0x18, 0xba, 0x74, 0x64, 0x73, 0x7c, 0xe5, 0x11, 0x33, 0x9b, - 0xfe, 0x92, 0x8e, 0x15, 0x81, 0x55, 0xd5, 0x4c, 0x7d, 0x41, 0x84, 0x7e, 0x07, 0x75, 0x2f, 0x18, - 0xc8, 0xb8, 0x68, 0xea, 0x9c, 0xa4, 0xfe, 0x24, 0x0d, 0x75, 0x4f, 0x33, 0x58, 0xb5, 0x98, 0x4b, - 0x91, 0x7f, 0x04, 0x8d, 0x84, 0xdc, 0xa5, 0x8e, 0x3b, 0x20, 0xcc, 0xcc, 0x37, 0xb3, 0xed, 0xbc, - 0xb5, 0x1a, 0xcb, 0xbb, 0x4a, 0x2c, 0xec, 0x18, 0x8e, 0xe9, 0x60, 0xc6, 0x8e, 0x42, 0x7a, 0x3b, - 0x8e, 0x34, 0x83, 0x55, 0x8b, 0xb9, 0x94, 0x1d, 0x97, 0xb0, 0x8a, 0x39, 0x8f, 0xdc, 0xab, 0x31, - 0x27, 0x9a, 0xbd, 0x28, 0xd9, 0x3f, 0xfc, 0x8e, 0xcc, 0x7d, 0x4e, 0x26, 0x32, 0xb8, 0x3a, 0x5b, - 0xeb, 0x09, 0x8b, 0xe2, 0xbd, 0x9a, 0xe5, 0x1d, 0x53, 0x97, 0x33, 0xb3, 0x94, 0xbe, 0x46, 0xf7, - 0x63, 0x8a, 0x0b, 0xea, 0xf2, 0x99, 0x33, 0xc4, 0x52, 0xd4, 0x1a, 0x78, 0x2e, 0xbd, 0xd1, 0x66, - 0x97, 0x25, 0xfd, 0xa3, 0x54, 0xc1, 0x71, 0xe9, 0x8d, 0x55, 0x16, 0x1c, 0xca, 0xe8, 0xf7, 0xa1, - 0xca, 0x78, 0x34, 0x4d, 0x25, 0x68, 0x66, 0xdb, 0x65, 0xab, 0xa2, 0x64, 0x0a, 0x72, 0x1f, 0x80, - 0xbb, 0x3e, 0xb1, 0x29, 0xa6, 0x01, 0x33, 0x2b, 0x4d, 0xa3, 0x9d, 0xb5, 0xca, 0x42, 0x72, 0x22, - 0x04, 0xe8, 0x03, 0xa8, 0x3b, 0xe3, 0x48, 0x85, 0x55, 0x41, 0xaa, 0x12, 0x52, 0x8b, 0xa5, 0x0a, - 0xf6, 0x05, 0x54, 0x42, 0x12, 0xb9, 0x81, 0xa3, 0x0a, 0xab, 0x26, 0x7b, 0xc5, 0xdb, 0x15, 0x96, - 0xbe, 0x7f, 0x50, 0x7c, 0xb2, 0xbc, 0x36, 0xa0, 0xa0, 0x56, 0x66, 0x5d, 0x1e, 0xae, 0x57, 0xe8, - 0x63, 0x40, 0x22, 0x7e, 0x84, 0x72, 0x5b, 0xba, 0xa4, 0xb2, 0x6e, 0x55, 0x66, 0xdd, 0x9a, 0xd6, - 0x9c, 0x27, 0x0a, 0xf4, 0x4b, 0xf8, 0x91, 0x43, 0x86, 0x78, 0xec, 0x71, 0x7b, 0xa6, 0x0b, 0xe8, - 0xad, 0xe4, 0xa5, 0xd9, 0x68, 0x1a, 0xed, 0xbc, 0xf5, 0x03, 0x8d, 0x39, 0x4f, 0xca, 0xfb, 0x5c, - 0x03, 0xd0, 0x15, 0x80, 0xb6, 0xde, 0x76, 0x1d, 0x73, 0xad, 0x69, 0xb4, 0xab, 0x07, 0x4f, 0x85, - 0xb5, 0xff, 0xfc, 0xe6, 0xc1, 0xcf, 0x47, 0xc1, 0x82, 0xbb, 0xae, 0x78, 0xfb, 0x3c, 0x8f, 0x0c, - 0x78, 0x10, 0xed, 0x84, 0x0e, 0xe6, 0x78, 0xc7, 0xa5, 0x9c, 0x44, 0x14, 0x7b, 0x3b, 0x62, 0x15, - 0xb7, 0xb2, 0x6e, 0xc7, 0x2a, 0x6b, 0xda, 0xae, 0x83, 0x8e, 0x01, 0x92, 0xac, 0x60, 0x26, 0x7a, - 0x9b, 0xd4, 0x9d, 0x21, 0x40, 0x9f, 0x82, 0xe9, 0x44, 0x41, 0x18, 0x12, 0xc7, 0x9e, 0x4a, 0xed, - 0x41, 0x30, 0xa6, 0xdc, 0x7c, 0xa7, 0x69, 0xb4, 0x6b, 0xd6, 0x86, 0xd6, 0x27, 0xa9, 0xc9, 0x9e, - 0x0a, 0x2d, 0xfa, 0x19, 0xbc, 0x1b, 0x44, 0xee, 0xc8, 0xa5, 0xd8, 0xb3, 0x43, 0x3c, 0xf1, 0x02, - 0xec, 0xd8, 0xc3, 0x20, 0xf2, 0x31, 0x37, 0xd7, 0x65, 0x8f, 0xbd, 0x17, 0xab, 0xcf, 0x94, 0xf6, - 0x48, 0x2a, 0x45, 0x23, 0x58, 0xdc, 0x67, 0xde, 0x13, 0x57, 0x65, 0xad, 0x2e, 0x6c, 0x68, 0xfd, - 0x01, 0x6a, 0x73, 0x05, 0x81, 0x3e, 0x81, 0x8d, 0x69, 0x91, 0xdd, 0x90, 0xc9, 0x34, 0x36, 0x86, - 0x8c, 0xcd, 0x7a, 0xa2, 0x7d, 0x4e, 0x26, 0x49, 0x58, 0x1e, 0x42, 0x4d, 0x14, 0xe4, 0x14, 0x9c, - 0x91, 0xe0, 0xaa, 0x10, 0xc6, 0xa0, 0xd6, 0xdf, 0x0d, 0xc8, 0x89, 0xf2, 0x40, 0x5f, 0x40, 0x89, - 0x47, 0x78, 0x20, 0x43, 0x68, 0xc8, 0x10, 0xee, 0xeb, 0x10, 0x3e, 0x49, 0x1f, 0xc2, 0xbe, 0x60, - 0xea, 0x76, 0xac, 0xa2, 0xa4, 0xec, 0x3a, 0xe8, 0x05, 0x14, 0x59, 0x88, 0xa9, 0x20, 0xcf, 0x48, - 0xf2, 0x5f, 0x69, 0xf2, 0x4f, 0xd3, 0x93, 0x9f, 0x87, 0x98, 0x76, 0x3b, 0x56, 0x41, 0x10, 0x76, - 0x9d, 0xd6, 0x3f, 0x0c, 0x28, 0x27, 0x55, 0x22, 0x9c, 0x9e, 0xcf, 0x5e, 0x75, 0x43, 0x55, 0x3e, - 0x9b, 0xb0, 0xdf, 0xe7, 0x66, 0xd0, 0x1f, 0xe1, 0x5d, 0x3c, 0x1a, 0x45, 0x64, 0xa4, 0x5f, 0x06, - 0xe2, 0x87, 0x41, 0x84, 0x3d, 0x97, 0x4f, 0xe4, 0x63, 0x5a, 0xdf, 0x3b, 0x48, 0xd5, 0xe1, 0xa6, - 0x54, 0xfd, 0x29, 0x93, 0xb5, 0x81, 0x97, 0xca, 0x5b, 0x5f, 0x66, 0xa0, 0xa0, 0x2a, 0x0d, 0xed, - 0xc1, 0xbd, 0xf8, 0xa5, 0x60, 0x36, 0xe3, 0x38, 0xe2, 0xf6, 0xac, 0x67, 0xef, 0x24, 0xca, 0x73, - 0xa1, 0xeb, 0x4a, 0xdb, 0x67, 0x5e, 0x1d, 0x66, 0x7b, 0x84, 0x8e, 0xf8, 0xb5, 0xf6, 0x31, 0x79, - 0x75, 0x58, 0x4f, 0x8a, 0xd1, 0x3a, 0xe4, 0x6f, 0xc5, 0xed, 0xc9, 0xf7, 0x34, 0x6b, 0xa9, 0x05, - 0xfa, 0x09, 0xac, 0x4d, 0x33, 0x2e, 0xee, 0x20, 0x39, 0xd9, 0x41, 0x1a, 0x89, 0x22, 0x7e, 0xb8, - 0x1e, 0xe8, 0xfe, 0xac, 0xcc, 0xca, 0x8b, 0x73, 0x3e, 0x5b, 0x51, 0xfd, 0x56, 0x99, 0xf3, 0x08, - 0xd6, 0x45, 0xeb, 0x64, 0x1c, 0xfb, 0x21, 0x13, 0xaf, 0xc4, 0x4b, 0xd9, 0x34, 0xe5, 0xfb, 0x96, - 0xb3, 0xd0, 0x54, 0x77, 0x41, 0xdd, 0x97, 0xa2, 0x73, 0x1e, 0xd4, 0xa0, 0x32, 0xa5, 0xb4, 0x5b, - 0x7f, 0x32, 0x20, 0xdf, 0xc3, 0x57, 0xc4, 0x13, 0xad, 0x7b, 0x49, 0x01, 0x54, 0x6e, 0x66, 0xf2, - 0x5e, 0x75, 0xf7, 0xc5, 0xe0, 0x8a, 0xee, 0x9e, 0x40, 0x1a, 0x90, 0xa5, 0x63, 0x5f, 0xc6, 0x31, - 0x6b, 0x89, 0x4f, 0xb4, 0x05, 0x6b, 0x74, 0xec, 0xdb, 0xf3, 0x69, 0x91, 0x53, 0x57, 0x46, 0xc7, - 0xfe, 0xc5, 0x6c, 0xcd, 0xfc, 0x27, 0x03, 0x45, 0x3d, 0x4a, 0x88, 0xc3, 0x7c, 0xe2, 0x07, 0xd1, - 0x44, 0x85, 0x46, 0xda, 0x93, 0xb3, 0x2a, 0x4a, 0x26, 0x23, 0x32, 0x03, 0xf1, 0x5c, 0xdf, 0xe5, - 0xd2, 0x9e, 0x04, 0xd2, 0x13, 0x22, 0xf4, 0x00, 0x2a, 0xb2, 0x7d, 0x06, 0xc3, 0x21, 0x23, 0x5c, - 0xda, 0x95, 0xb3, 0x40, 0x88, 0x4e, 0xa5, 0x44, 0xc4, 0x43, 0xac, 0x28, 0xf6, 0xc9, 0xa2, 0x79, - 0x8d, 0x58, 0x91, 0x78, 0xb7, 0x34, 0x78, 0xf9, 0x3b, 0x82, 0xf7, 0x10, 0x6a, 0xd7, 0x98, 0xd9, - 0xf1, 0xb4, 0xc0, 0xcc, 0x42, 0xd3, 0x68, 0x97, 0xac, 0xea, 0x35, 0x66, 0xf1, 0x2c, 0x31, 0x05, - 0xe9, 0x93, 0x98, 0x59, 0x9c, 0x82, 0x62, 0x19, 0x6a, 0x43, 0x43, 0x80, 0x3c, 0x97, 0x12, 0x9b, - 0x8e, 0xfd, 0x2b, 0x12, 0x89, 0x59, 0x40, 0xe0, 0xea, 0xd7, 0x98, 0xf5, 0x5c, 0x4a, 0x4e, 0x94, - 0x54, 0x5c, 0xb6, 0x40, 0xba, 0x54, 0x62, 0x87, 0x91, 0xa4, 0x2c, 0x4b, 0xe8, 0xea, 0x35, 0x66, - 0x5d, 0x29, 0x3f, 0x92, 0xe2, 0xd6, 0x7f, 0x0d, 0x28, 0xc5, 0xc3, 0x15, 0xfa, 0x60, 0x3a, 0x04, - 0xce, 0x84, 0xff, 0xb3, 0x95, 0x64, 0xa2, 0x53, 0xf9, 0x66, 0x42, 0x11, 0x3b, 0x4e, 0x44, 0x18, - 0xd3, 0x97, 0x1d, 0x2f, 0x51, 0x07, 0x72, 0x82, 0x5b, 0x0f, 0x8f, 0x69, 0x87, 0x08, 0x62, 0xc9, - 0xdd, 0xe8, 0x87, 0x50, 0x76, 0x99, 0x3d, 0x0c, 0x3c, 0x87, 0x38, 0x32, 0x0a, 0x25, 0xab, 0xe4, - 0xb2, 0x23, 0xb9, 0x4e, 0x75, 0xfb, 0x07, 0x0d, 0xa8, 0xcf, 0x39, 0x64, 0xb7, 0x5e, 0xc8, 0x7e, - 0x4c, 0xc4, 0x84, 0x91, 0x4c, 0x83, 0xb3, 0xa9, 0x9e, 0xcc, 0x75, 0xca, 0x55, 0xa4, 0x1d, 0xca, - 0xc8, 0x54, 0x56, 0xe6, 0x6d, 0x40, 0x61, 0x10, 0x78, 0x63, 0x9f, 0xea, 0x04, 0xd7, 0xab, 0xd6, - 0xdf, 0x0c, 0x28, 0xc5, 0x31, 0x15, 0x21, 0x9d, 0xcf, 0x26, 0xdd, 0x28, 0xe7, 0x32, 0xe9, 0x11, - 0xac, 0xb3, 0x09, 0xe3, 0xc4, 0xb7, 0xe7, 0xb1, 0xaa, 0xa4, 0x90, 0xd2, 0x9d, 0x2c, 0xe4, 0xde, - 0xff, 0x27, 0x6a, 0xf6, 0x8e, 0x44, 0x15, 0xff, 0xa2, 0xc8, 0x86, 0x26, 0x5d, 0xc8, 0xa9, 0x21, - 0x4b, 0x4a, 0xc4, 0x15, 0x6c, 0x7d, 0x69, 0xc0, 0xc6, 0xf2, 0xbe, 0x89, 0x3e, 0x84, 0x87, 0xfb, - 0xcf, 0x9e, 0x59, 0x87, 0xcf, 0xf6, 0xfb, 0xdd, 0xd3, 0x13, 0xbb, 0x7f, 0x78, 0x7c, 0x76, 0x6a, - 0xed, 0xf7, 0xba, 0xfd, 0x17, 0xf6, 0xc5, 0xc9, 0xf9, 0xd9, 0xe1, 0xd3, 0xee, 0x51, 0xf7, 0xb0, - 0xd3, 0x58, 0x41, 0xef, 0xc3, 0xfd, 0xbb, 0x80, 0x9d, 0xc3, 0x5e, 0x7f, 0xbf, 0x61, 0xa0, 0x1f, - 0x43, 0xeb, 0x2e, 0xc8, 0xd3, 0x8b, 0xe3, 0x8b, 0xde, 0x7e, 0xbf, 0x7b, 0x79, 0xd8, 0xc8, 0x1c, - 0x7c, 0x6d, 0x7c, 0xf5, 0x7a, 0xd3, 0x78, 0xf5, 0x7a, 0xd3, 0xf8, 0xd7, 0xeb, 0x4d, 0xe3, 0xcf, - 0x6f, 0x36, 0x57, 0x5e, 0xbd, 0xd9, 0x5c, 0xf9, 0xfa, 0xcd, 0xe6, 0x0a, 0x7c, 0xec, 0x06, 0x29, - 0x52, 0xe9, 0xa0, 0x16, 0xff, 0x1b, 0x79, 0x26, 0x50, 0x67, 0xc6, 0x6f, 0x7f, 0x9d, 0xfa, 0x15, - 0x54, 0xbf, 0x0c, 0x8c, 0x08, 0xbd, 0xe3, 0x57, 0x8c, 0xbf, 0x66, 0xb6, 0x4e, 0x43, 0x42, 0xfb, - 0x09, 0xa1, 0x3c, 0x2a, 0x9e, 0xad, 0xd8, 0xf6, 0xe5, 0x6e, 0x67, 0x0a, 0xbe, 0x2a, 0x48, 0xb6, - 0xc7, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, 0xbc, 0x31, 0xf3, 0xe8, 0x27, 0x11, 0x00, 0x00, + // 1591 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x58, 0xdb, 0x6f, 0x13, 0x57, + 0x1a, 0xcf, 0xd8, 0x8e, 0x2f, 0x9f, 0x2f, 0x71, 0x0e, 0x21, 0xcc, 0xb2, 0x4b, 0x62, 0x8c, 0x58, + 0x4c, 0x56, 0x24, 0x24, 0xb0, 0x2b, 0xd0, 0xae, 0xb4, 0x9b, 0xc4, 0x09, 0x18, 0x42, 0x92, 0x9d, + 0x38, 0x51, 0x69, 0x91, 0xa6, 0x27, 0x9e, 0x63, 0x67, 0xca, 0xdc, 0x34, 0xe7, 0x38, 0xc2, 0xea, + 0xbf, 0xc0, 0x43, 0xff, 0x8e, 0x4a, 0xfd, 0x1b, 0xfa, 0xca, 0x23, 0xea, 0x13, 0xea, 0x03, 0xaa, + 0xe0, 0x85, 0x56, 0xea, 0x6b, 0x9f, 0xab, 0x73, 0x99, 0xb1, 0x9d, 0x3a, 0x82, 0xe9, 0x4b, 0x34, + 0xe7, 0x3b, 0xbf, 0xf3, 0x3b, 0xdf, 0xfd, 0x3b, 0x0e, 0xdc, 0xf7, 0x03, 0xe2, 0x31, 0xe2, 0x10, + 0x97, 0xb0, 0x70, 0xb0, 0x12, 0x84, 0x3e, 0xf3, 0xf9, 0xdf, 0xae, 0xed, 0x10, 0xba, 0x72, 0xba, + 0x6a, 0x91, 0x53, 0xe2, 0xf8, 0x81, 0x4b, 0x3c, 0x16, 0x8b, 0x97, 0x05, 0x0a, 0x2d, 0x8d, 0x1d, + 0x95, 0xc2, 0xe5, 0x18, 0x33, 0x76, 0xf4, 0xf2, 0x5c, 0xcf, 0xef, 0xf9, 0x92, 0x9c, 0x7f, 0x49, + 0xf0, 0xe5, 0xa5, 0x49, 0x97, 0x77, 0x7c, 0xd7, 0xf5, 0xbd, 0x95, 0xd3, 0x55, 0xf5, 0xa5, 0xb0, + 0xcb, 0x93, 0xb0, 0x21, 0xa1, 0x7e, 0x3f, 0xec, 0x10, 0x8e, 0x8e, 0xbe, 0x25, 0xbe, 0x3e, 0x80, + 0xd2, 0xbe, 0xd2, 0xa5, 0x89, 0x19, 0x46, 0x36, 0xcc, 0x46, 0x08, 0x33, 0x52, 0x52, 0xd7, 0x6a, + 0xe9, 0x46, 0x71, 0xed, 0x3f, 0xcb, 0x9f, 0x6e, 0xc9, 0xb2, 0xa1, 0x48, 0x22, 0x72, 0xa3, 0x1a, + 0x9e, 0x91, 0xd4, 0x3f, 0x68, 0x50, 0x3d, 0x0b, 0x43, 0x8f, 0x21, 0x1f, 0x01, 0x75, 0xad, 0xa6, + 0x35, 0x8a, 0x6b, 0x37, 0x27, 0x5e, 0x1b, 0x9b, 0x71, 0xba, 0x1a, 0xdf, 0xb5, 0x91, 0x79, 0xf5, + 0x76, 0x71, 0xca, 0x88, 0x09, 0xd0, 0x97, 0x50, 0xa1, 0x1d, 0x3f, 0x18, 0xb1, 0x24, 0x25, 0x2c, + 0xb9, 0x9f, 0xc4, 0x92, 0x03, 0xce, 0x10, 0x9b, 0x51, 0xa6, 0xa3, 0x4b, 0x74, 0x05, 0x80, 0x76, + 0x4e, 0x88, 0x8b, 0xcd, 0x7e, 0xe8, 0xe8, 0xe9, 0x9a, 0xd6, 0x28, 0x18, 0x05, 0x29, 0x39, 0x0c, + 0x9d, 0x47, 0xd9, 0xfc, 0x87, 0x5c, 0xf5, 0xe7, 0x5c, 0xfd, 0xb5, 0x06, 0xe5, 0x31, 0x1e, 0xb4, + 0x07, 0xd3, 0x82, 0x49, 0x19, 0x79, 0x67, 0xa2, 0x46, 0x2a, 0xb2, 0xa7, 0xab, 0xcb, 0x2d, 0x8f, + 0xb2, 0xb0, 0xcf, 0xf5, 0xc1, 0xcc, 0xf6, 0x3d, 0xc1, 0xa5, 0xcc, 0x95, 0x3c, 0x68, 0x0f, 0xf2, + 0x67, 0xac, 0xbc, 0x93, 0xc4, 0x4a, 0xa5, 0x98, 0x11, 0x93, 0x7c, 0xc4, 0xb4, 0xfa, 0x6f, 0x00, + 0x39, 0x75, 0x08, 0x1d, 0x41, 0x91, 0x62, 0x37, 0x70, 0x88, 0xc9, 0x06, 0xc2, 0x24, 0x7e, 0xfd, + 0x3f, 0x93, 0x5c, 0x7f, 0x84, 0x9d, 0x3e, 0x69, 0x0f, 0x02, 0x62, 0x80, 0x64, 0xe2, 0xdf, 0xe8, + 0x11, 0x64, 0xe5, 0x4a, 0x59, 0xb4, 0x96, 0x28, 0x6e, 0xe2, 0xa4, 0xa1, 0x18, 0xd0, 0x67, 0x50, + 0x76, 0x71, 0x10, 0xd8, 0x5e, 0xcf, 0x64, 0xf8, 0xd8, 0x21, 0x7a, 0x3a, 0xb9, 0x93, 0x9e, 0x48, + 0x02, 0xa3, 0xa4, 0x98, 0xda, 0x9c, 0x08, 0x7d, 0x01, 0x15, 0xc7, 0xef, 0x88, 0xb8, 0x28, 0xea, + 0x8c, 0xa0, 0xbe, 0x9b, 0x84, 0x7a, 0x47, 0x31, 0x18, 0xe5, 0x88, 0x4b, 0x92, 0xdf, 0x84, 0x6a, + 0x4c, 0x6e, 0x7b, 0x96, 0xdd, 0x21, 0x54, 0x9f, 0xae, 0xa5, 0x1b, 0xd3, 0xc6, 0x4c, 0x24, 0x6f, + 0x49, 0x31, 0xd7, 0xa3, 0xdb, 0xf7, 0x3a, 0x23, 0x7a, 0x64, 0x93, 0xeb, 0xb1, 0xad, 0x18, 0x8c, + 0x72, 0xc4, 0x25, 0xf5, 0x38, 0x82, 0x19, 0xcc, 0x58, 0x68, 0x1f, 0xf7, 0x19, 0x51, 0xec, 0x39, + 0xc1, 0x7e, 0xe3, 0x23, 0x99, 0xfb, 0x98, 0x0c, 0x44, 0x70, 0x55, 0xb6, 0x56, 0x62, 0x16, 0xc9, + 0x7b, 0x3c, 0xca, 0xdb, 0xf7, 0x6c, 0x46, 0xf5, 0x7c, 0xf2, 0x1a, 0x5d, 0x8f, 0x28, 0x0e, 0x3d, + 0x9b, 0x8d, 0xdc, 0xc1, 0x97, 0xbc, 0xd6, 0xc0, 0xb1, 0xbd, 0xe7, 0x4a, 0xed, 0x82, 0xa0, 0xbf, + 0x9d, 0x28, 0x38, 0xb6, 0xf7, 0xdc, 0x28, 0x70, 0x0e, 0xa9, 0xf4, 0x55, 0x28, 0x51, 0x16, 0x0e, + 0x53, 0x09, 0x6a, 0xe9, 0x46, 0xc1, 0x28, 0x4a, 0x99, 0x84, 0x5c, 0x01, 0x60, 0xb6, 0x4b, 0x4c, + 0x0f, 0x7b, 0x3e, 0xd5, 0x8b, 0x35, 0xad, 0x91, 0x36, 0x0a, 0x5c, 0xb2, 0xcb, 0x05, 0xe8, 0x3a, + 0x54, 0xac, 0x7e, 0x28, 0xc3, 0x2a, 0x21, 0x25, 0x01, 0x29, 0x47, 0x52, 0x09, 0x7b, 0x06, 0xc5, + 0x80, 0x84, 0xb6, 0x6f, 0xc9, 0xc2, 0x2a, 0x8b, 0x5e, 0xf1, 0xe7, 0x0a, 0x4b, 0xf9, 0x1f, 0x24, + 0x9f, 0x28, 0xaf, 0x79, 0xc8, 0xca, 0x95, 0x5e, 0x11, 0x97, 0xab, 0x15, 0xba, 0x05, 0x88, 0xc7, + 0x8f, 0x78, 0xcc, 0x14, 0x26, 0xc9, 0xac, 0x9b, 0x11, 0x59, 0x37, 0xab, 0x76, 0x0e, 0xe2, 0x0d, + 0xf4, 0x5f, 0xf8, 0x9b, 0x45, 0xba, 0xb8, 0xef, 0x30, 0x73, 0xa4, 0x0b, 0xa8, 0xa3, 0xe4, 0x85, + 0x5e, 0xad, 0x69, 0x8d, 0x69, 0xe3, 0x2f, 0x0a, 0x73, 0x10, 0x97, 0xf7, 0x81, 0x02, 0xa0, 0x63, + 0x00, 0xa5, 0xbd, 0x69, 0x5b, 0xfa, 0x6c, 0x4d, 0x6b, 0x94, 0x36, 0x36, 0xb9, 0xb6, 0x3f, 0xbe, + 0x5d, 0xfc, 0x77, 0xcf, 0x3f, 0x63, 0xae, 0xcd, 0x67, 0x9f, 0xe3, 0x90, 0x0e, 0xf3, 0xc3, 0x95, + 0xc0, 0xc2, 0x0c, 0xaf, 0xd8, 0x1e, 0x23, 0xa1, 0x87, 0x9d, 0x15, 0xbe, 0x8a, 0x5a, 0x59, 0xab, + 0x69, 0x14, 0x14, 0x6d, 0xcb, 0x42, 0xf7, 0x40, 0xb7, 0x42, 0x3f, 0x08, 0x88, 0x65, 0xc6, 0xd9, + 0x41, 0xcd, 0x8e, 0xdf, 0xf7, 0x98, 0x7e, 0xa1, 0xa6, 0x35, 0xca, 0xc6, 0xbc, 0xda, 0x8f, 0x73, + 0x89, 0x6e, 0xf2, 0x5d, 0xf4, 0x2f, 0xb8, 0xe4, 0x87, 0x76, 0xcf, 0xf6, 0xb0, 0x63, 0x06, 0x78, + 0xe0, 0xf8, 0xd8, 0x32, 0xbb, 0x7e, 0xe8, 0x62, 0xa6, 0xcf, 0x89, 0xa6, 0x78, 0x31, 0xda, 0xde, + 0x97, 0xbb, 0xdb, 0x62, 0x93, 0x57, 0xee, 0xd9, 0x73, 0xfa, 0x45, 0x6e, 0x9b, 0x31, 0x73, 0xe6, + 0x00, 0xfa, 0x07, 0xcc, 0x0e, 0x8b, 0x20, 0xf2, 0xf7, 0xbc, 0xf0, 0x77, 0x35, 0xde, 0x50, 0x65, + 0x5e, 0xff, 0x0a, 0xca, 0x63, 0xe9, 0x8e, 0xee, 0xc2, 0xfc, 0xf0, 0xf4, 0x73, 0x32, 0x18, 0x7a, + 0x5e, 0x13, 0x9e, 0x9f, 0x8b, 0x77, 0x1f, 0x93, 0x41, 0xec, 0xf4, 0x6b, 0x50, 0xe6, 0xe5, 0x36, + 0x04, 0xa7, 0x04, 0xb8, 0xc4, 0x85, 0x11, 0xa8, 0xfe, 0xbd, 0x06, 0x19, 0x9e, 0xfc, 0xe8, 0x19, + 0xe4, 0x59, 0x88, 0x3b, 0x22, 0x40, 0x9a, 0x08, 0xd0, 0xba, 0x0a, 0xd0, 0xfd, 0xe4, 0x01, 0x6a, + 0x73, 0xa6, 0x56, 0xd3, 0xc8, 0x09, 0xca, 0x96, 0x85, 0x9e, 0x42, 0x8e, 0x06, 0xd8, 0xe3, 0xe4, + 0x29, 0x41, 0xfe, 0x3f, 0x45, 0x7e, 0x2f, 0x39, 0xf9, 0x41, 0x80, 0xbd, 0x56, 0xd3, 0xc8, 0x72, + 0xc2, 0x96, 0x55, 0xff, 0x41, 0x83, 0x42, 0x5c, 0x03, 0xdc, 0xe8, 0xf1, 0xdc, 0x94, 0x1e, 0x2a, + 0xb1, 0xd1, 0x74, 0xfc, 0x14, 0xcf, 0xa0, 0xaf, 0xe1, 0x12, 0xee, 0xf5, 0x42, 0xd2, 0x53, 0x7d, + 0x9f, 0xb8, 0x81, 0x1f, 0x62, 0xc7, 0x66, 0x03, 0x31, 0x2a, 0x2b, 0x6b, 0x1b, 0x89, 0xfa, 0xd7, + 0x90, 0xaa, 0x3d, 0x64, 0x32, 0xe6, 0xf1, 0x44, 0x79, 0xfd, 0x65, 0x0a, 0xb2, 0xb2, 0x8e, 0xd0, + 0x1a, 0x5c, 0x8c, 0xe6, 0x00, 0x35, 0x29, 0xc3, 0x21, 0x33, 0x47, 0x2d, 0xbb, 0x10, 0x6f, 0x1e, + 0xf0, 0xbd, 0x96, 0xd0, 0x7d, 0x64, 0xa6, 0x50, 0xd3, 0x21, 0x5e, 0x8f, 0x9d, 0x28, 0x1b, 0xe3, + 0x99, 0x42, 0x77, 0x84, 0x18, 0xcd, 0xc1, 0xf4, 0x29, 0xf7, 0x9e, 0x98, 0x96, 0x69, 0x43, 0x2e, + 0x26, 0xe7, 0x6b, 0x66, 0x72, 0xbe, 0xa2, 0x45, 0xd5, 0x7d, 0xa5, 0x5a, 0xd3, 0xfc, 0x9e, 0x87, + 0x53, 0xb2, 0x9b, 0x4a, 0x75, 0x6e, 0xc3, 0x1c, 0x6f, 0x8c, 0x94, 0x61, 0x37, 0xa0, 0x7c, 0x06, + 0xbc, 0x10, 0x2d, 0x51, 0x4c, 0xaf, 0x8c, 0x81, 0x86, 0x7b, 0x87, 0x9e, 0xfd, 0x82, 0xf7, 0xc5, + 0x8d, 0x32, 0x14, 0x87, 0x94, 0x66, 0xfd, 0x97, 0x14, 0xe4, 0xd4, 0x68, 0xe6, 0xad, 0xd9, 0x25, + 0xae, 0x1f, 0x0e, 0xa4, 0x33, 0x84, 0x1b, 0x32, 0x46, 0x51, 0xca, 0x84, 0x0f, 0x46, 0x20, 0x8e, + 0xed, 0xda, 0x4c, 0x98, 0x1e, 0x43, 0x76, 0xb8, 0x08, 0x2d, 0x42, 0x51, 0xb4, 0x23, 0xbf, 0xdb, + 0xa5, 0x84, 0x89, 0x88, 0x66, 0x0c, 0xe0, 0xa2, 0x3d, 0x21, 0xe1, 0x1e, 0xe0, 0x2b, 0x0f, 0xbb, + 0x23, 0xc9, 0x94, 0x11, 0x3e, 0xac, 0x46, 0x1b, 0x71, 0xae, 0x4c, 0x74, 0xd7, 0xf4, 0x39, 0xee, + 0xba, 0x06, 0xe5, 0x13, 0x4c, 0xcd, 0x68, 0xfa, 0x52, 0x3d, 0x5b, 0xd3, 0x1a, 0x79, 0xa3, 0x74, + 0x82, 0x69, 0x34, 0x9b, 0x87, 0x20, 0x75, 0x13, 0xd5, 0x73, 0x43, 0x50, 0x24, 0x43, 0x0d, 0xa8, + 0x72, 0x90, 0x63, 0x7b, 0xc4, 0xf4, 0xfa, 0xee, 0x31, 0x09, 0xf9, 0x6c, 0xe5, 0xb8, 0xca, 0x09, + 0xa6, 0x3b, 0xb6, 0x47, 0x76, 0xa5, 0x14, 0x2d, 0xc1, 0x2c, 0x47, 0xda, 0x9e, 0xc0, 0x76, 0x43, + 0x41, 0x59, 0x10, 0xd0, 0x99, 0x13, 0x4c, 0x5b, 0x42, 0xbe, 0x2d, 0xc4, 0xf5, 0x5f, 0x35, 0xc8, + 0x47, 0x8f, 0x15, 0x74, 0x7d, 0xf8, 0xa8, 0x1a, 0xc9, 0xba, 0x87, 0x53, 0xf1, 0x0b, 0x49, 0x46, + 0x58, 0x87, 0x1c, 0xb6, 0xac, 0x90, 0x50, 0xaa, 0x9c, 0x1d, 0x2d, 0x51, 0x13, 0x32, 0x9c, 0x5b, + 0x3d, 0xc6, 0x92, 0x0e, 0x65, 0x62, 0x88, 0xd3, 0xe8, 0xaf, 0x50, 0xb0, 0xa9, 0xd9, 0xf5, 0x1d, + 0x8b, 0x58, 0x22, 0x0a, 0x79, 0x23, 0x6f, 0xd3, 0x6d, 0xb1, 0x4e, 0xe4, 0xfd, 0x8d, 0x2a, 0x54, + 0xc6, 0x0c, 0x32, 0xeb, 0x4f, 0x45, 0x07, 0x24, 0x7c, 0x62, 0xc7, 0xaf, 0xab, 0xd1, 0x0a, 0x8b, + 0xdf, 0x49, 0xd2, 0x54, 0xa4, 0x0c, 0x4a, 0x89, 0x89, 0x2a, 0xd5, 0x9b, 0x87, 0x6c, 0xc7, 0x77, + 0xfa, 0xae, 0x27, 0x12, 0x29, 0x6d, 0xa8, 0x55, 0xfd, 0x3b, 0x0d, 0xf2, 0x51, 0x4c, 0x79, 0x48, + 0xc7, 0xb3, 0x49, 0xb5, 0xa6, 0xb1, 0x4c, 0xba, 0x0d, 0x73, 0x74, 0x40, 0x19, 0x71, 0xcd, 0x71, + 0xac, 0xac, 0x5e, 0x24, 0xf7, 0x76, 0xcf, 0xe4, 0xde, 0x1f, 0x13, 0x35, 0x7d, 0x4e, 0xa2, 0xf2, + 0x27, 0xbf, 0x68, 0x21, 0xc2, 0x84, 0x8c, 0x7c, 0xb4, 0x08, 0x09, 0x77, 0xc1, 0xd2, 0x4b, 0x0d, + 0xe6, 0x27, 0x77, 0x2a, 0x74, 0x03, 0xae, 0xad, 0x3f, 0x78, 0x60, 0x6c, 0x3d, 0x58, 0x6f, 0xb7, + 0xf6, 0x76, 0xcd, 0xf6, 0xd6, 0x93, 0xfd, 0x3d, 0x63, 0x7d, 0xa7, 0xd5, 0x7e, 0x6a, 0x1e, 0xee, + 0x1e, 0xec, 0x6f, 0x6d, 0xb6, 0xb6, 0x5b, 0x5b, 0xcd, 0xea, 0x14, 0xba, 0x0a, 0x57, 0xce, 0x03, + 0x36, 0xb7, 0x76, 0xda, 0xeb, 0x55, 0x0d, 0xfd, 0x1d, 0xea, 0xe7, 0x41, 0x36, 0x0f, 0x9f, 0x1c, + 0xee, 0xac, 0xb7, 0x5b, 0x47, 0x5b, 0xd5, 0xd4, 0xc6, 0x1b, 0xed, 0xd5, 0xbb, 0x05, 0xed, 0xf5, + 0xbb, 0x05, 0xed, 0xa7, 0x77, 0x0b, 0xda, 0x37, 0xef, 0x17, 0xa6, 0x5e, 0xbf, 0x5f, 0x98, 0x7a, + 0xf3, 0x7e, 0x61, 0x0a, 0x6e, 0xd9, 0x7e, 0x82, 0x54, 0xda, 0x28, 0x47, 0x3f, 0xcb, 0xf6, 0x39, + 0x6a, 0x5f, 0xfb, 0xfc, 0xff, 0x89, 0xe7, 0x8e, 0xfc, 0xa5, 0xdd, 0x23, 0xde, 0x39, 0xff, 0x15, + 0xf8, 0x36, 0xb5, 0xb4, 0x17, 0x10, 0xaf, 0x1d, 0x13, 0x8a, 0xab, 0xa2, 0xb7, 0x0a, 0x5d, 0x3e, + 0x5a, 0x6d, 0x0e, 0xc1, 0xc7, 0x59, 0xc1, 0x76, 0xe7, 0xf7, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd8, + 0x20, 0xd9, 0xad, 0x77, 0x10, 0x00, 0x00, } func (m *ProfilesData) Marshal() (dAtA []byte, err error) { @@ -1620,6 +1541,27 @@ func (m *Profile) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.AttributeIndices) > 0 { + dAtA4 := make([]byte, len(m.AttributeIndices)*10) + var j3 int + for _, num1 := range m.AttributeIndices { + num := uint64(num1) + for num >= 1<<7 { + dAtA4[j3] = uint8(uint64(num)&0x7f | 0x80) + num >>= 7 + j3++ + } + dAtA4[j3] = uint8(num) + j3++ + } + i -= j3 + copy(dAtA[i:], dAtA4[:j3]) + i = encodeVarintProfiles(dAtA, i, uint64(j3)) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xb2 + } if len(m.OriginalPayload) > 0 { i -= len(m.OriginalPayload) copy(dAtA[i:], m.OriginalPayload) @@ -1645,22 +1587,6 @@ func (m *Profile) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x98 } - if len(m.Attributes) > 0 { - for iNdEx := len(m.Attributes) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Attributes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintProfiles(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1 - i-- - dAtA[i] = 0x92 - } - } { size := m.ProfileId.Size() i -= size @@ -1681,21 +1607,21 @@ func (m *Profile) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x80 } if len(m.CommentStrindices) > 0 { - dAtA4 := make([]byte, len(m.CommentStrindices)*10) - var j3 int + dAtA6 := make([]byte, len(m.CommentStrindices)*10) + var j5 int for _, num1 := range m.CommentStrindices { num := uint64(num1) for num >= 1<<7 { - dAtA4[j3] = uint8(uint64(num)&0x7f | 0x80) + dAtA6[j5] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j3++ + j5++ } - dAtA4[j3] = uint8(num) - j3++ + dAtA6[j5] = uint8(num) + j5++ } - i -= j3 - copy(dAtA[i:], dAtA4[:j3]) - i = encodeVarintProfiles(dAtA, i, uint64(j3)) + i -= j5 + copy(dAtA[i:], dAtA6[:j5]) + i = encodeVarintProfiles(dAtA, i, uint64(j5)) i-- dAtA[i] = 0x7a } @@ -1790,21 +1716,21 @@ func (m *Profile) MarshalToSizedBuffer(dAtA []byte) (int, error) { } } if len(m.LocationIndices) > 0 { - dAtA7 := make([]byte, len(m.LocationIndices)*10) - var j6 int + dAtA9 := make([]byte, len(m.LocationIndices)*10) + var j8 int for _, num1 := range m.LocationIndices { num := uint64(num1) for num >= 1<<7 { - dAtA7[j6] = uint8(uint64(num)&0x7f | 0x80) + dAtA9[j8] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j6++ + j8++ } - dAtA7[j6] = uint8(num) - j6++ + dAtA9[j8] = uint8(num) + j8++ } - i -= j6 - copy(dAtA[i:], dAtA7[:j6]) - i = encodeVarintProfiles(dAtA, i, uint64(j6)) + i -= j8 + copy(dAtA[i:], dAtA9[:j8]) + i = encodeVarintProfiles(dAtA, i, uint64(j8)) i-- dAtA[i] = 0x2a } @@ -2002,20 +1928,20 @@ func (m *Sample) MarshalToSizedBuffer(dAtA []byte) (int, error) { var l int _ = l if len(m.TimestampsUnixNano) > 0 { - dAtA9 := make([]byte, len(m.TimestampsUnixNano)*10) - var j8 int + dAtA11 := make([]byte, len(m.TimestampsUnixNano)*10) + var j10 int for _, num := range m.TimestampsUnixNano { for num >= 1<<7 { - dAtA9[j8] = uint8(uint64(num)&0x7f | 0x80) + dAtA11[j10] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j8++ + j10++ } - dAtA9[j8] = uint8(num) - j8++ + dAtA11[j10] = uint8(num) + j10++ } - i -= j8 - copy(dAtA[i:], dAtA9[:j8]) - i = encodeVarintProfiles(dAtA, i, uint64(j8)) + i -= j10 + copy(dAtA[i:], dAtA11[:j10]) + i = encodeVarintProfiles(dAtA, i, uint64(j10)) i-- dAtA[i] = 0x32 } @@ -2029,40 +1955,40 @@ func (m *Sample) MarshalToSizedBuffer(dAtA []byte) (int, error) { } } if len(m.AttributeIndices) > 0 { - dAtA11 := make([]byte, len(m.AttributeIndices)*10) - var j10 int + dAtA13 := make([]byte, len(m.AttributeIndices)*10) + var j12 int for _, num1 := range m.AttributeIndices { num := uint64(num1) for num >= 1<<7 { - dAtA11[j10] = uint8(uint64(num)&0x7f | 0x80) + dAtA13[j12] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j10++ + j12++ } - dAtA11[j10] = uint8(num) - j10++ + dAtA13[j12] = uint8(num) + j12++ } - i -= j10 - copy(dAtA[i:], dAtA11[:j10]) - i = encodeVarintProfiles(dAtA, i, uint64(j10)) + i -= j12 + copy(dAtA[i:], dAtA13[:j12]) + i = encodeVarintProfiles(dAtA, i, uint64(j12)) i-- dAtA[i] = 0x22 } if len(m.Value) > 0 { - dAtA13 := make([]byte, len(m.Value)*10) - var j12 int + dAtA15 := make([]byte, len(m.Value)*10) + var j14 int for _, num1 := range m.Value { num := uint64(num1) for num >= 1<<7 { - dAtA13[j12] = uint8(uint64(num)&0x7f | 0x80) + dAtA15[j14] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j12++ + j14++ } - dAtA13[j12] = uint8(num) - j12++ + dAtA15[j14] = uint8(num) + j14++ } - i -= j12 - copy(dAtA[i:], dAtA13[:j12]) - i = encodeVarintProfiles(dAtA, i, uint64(j12)) + i -= j14 + copy(dAtA[i:], dAtA15[:j14]) + i = encodeVarintProfiles(dAtA, i, uint64(j14)) i-- dAtA[i] = 0x1a } @@ -2091,49 +2017,6 @@ func (m *Sample_LinkIndex) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x28 return len(dAtA) - i, nil } -func (m *Label) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *Label) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Label) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.NumUnitStrindex != 0 { - i = encodeVarintProfiles(dAtA, i, uint64(m.NumUnitStrindex)) - i-- - dAtA[i] = 0x20 - } - if m.Num != 0 { - i = encodeVarintProfiles(dAtA, i, uint64(m.Num)) - i-- - dAtA[i] = 0x18 - } - if m.StrStrindex != 0 { - i = encodeVarintProfiles(dAtA, i, uint64(m.StrStrindex)) - i-- - dAtA[i] = 0x10 - } - if m.KeyStrindex != 0 { - i = encodeVarintProfiles(dAtA, i, uint64(m.KeyStrindex)) - i-- - dAtA[i] = 0x8 - } - return len(dAtA) - i, nil -} - func (m *Mapping) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -2195,21 +2078,21 @@ func (m *Mapping) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x30 } if len(m.AttributeIndices) > 0 { - dAtA15 := make([]byte, len(m.AttributeIndices)*10) - var j14 int + dAtA17 := make([]byte, len(m.AttributeIndices)*10) + var j16 int for _, num1 := range m.AttributeIndices { num := uint64(num1) for num >= 1<<7 { - dAtA15[j14] = uint8(uint64(num)&0x7f | 0x80) + dAtA17[j16] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j14++ + j16++ } - dAtA15[j14] = uint8(num) - j14++ + dAtA17[j16] = uint8(num) + j16++ } - i -= j14 - copy(dAtA[i:], dAtA15[:j14]) - i = encodeVarintProfiles(dAtA, i, uint64(j14)) + i -= j16 + copy(dAtA[i:], dAtA17[:j16]) + i = encodeVarintProfiles(dAtA, i, uint64(j16)) i-- dAtA[i] = 0x2a } @@ -2257,21 +2140,21 @@ func (m *Location) MarshalToSizedBuffer(dAtA []byte) (int, error) { var l int _ = l if len(m.AttributeIndices) > 0 { - dAtA17 := make([]byte, len(m.AttributeIndices)*10) - var j16 int + dAtA19 := make([]byte, len(m.AttributeIndices)*10) + var j18 int for _, num1 := range m.AttributeIndices { num := uint64(num1) for num >= 1<<7 { - dAtA17[j16] = uint8(uint64(num)&0x7f | 0x80) + dAtA19[j18] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j16++ + j18++ } - dAtA17[j16] = uint8(num) - j16++ + dAtA19[j18] = uint8(num) + j18++ } - i -= j16 - copy(dAtA[i:], dAtA17[:j16]) - i = encodeVarintProfiles(dAtA, i, uint64(j16)) + i -= j18 + copy(dAtA[i:], dAtA19[:j18]) + i = encodeVarintProfiles(dAtA, i, uint64(j18)) i-- dAtA[i] = 0x2a } @@ -2567,12 +2450,6 @@ func (m *Profile) Size() (n int) { } l = m.ProfileId.Size() n += 2 + l + sovProfiles(uint64(l)) - if len(m.Attributes) > 0 { - for _, e := range m.Attributes { - l = e.Size() - n += 2 + l + sovProfiles(uint64(l)) - } - } if m.DroppedAttributesCount != 0 { n += 2 + sovProfiles(uint64(m.DroppedAttributesCount)) } @@ -2584,6 +2461,13 @@ func (m *Profile) Size() (n int) { if l > 0 { n += 2 + l + sovProfiles(uint64(l)) } + if len(m.AttributeIndices) > 0 { + l = 0 + for _, e := range m.AttributeIndices { + l += sovProfiles(uint64(e)) + } + n += 2 + sovProfiles(uint64(l)) + l + } return n } @@ -2681,27 +2565,6 @@ func (m *Sample_LinkIndex) Size() (n int) { n += 1 + sovProfiles(uint64(m.LinkIndex)) return n } -func (m *Label) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.KeyStrindex != 0 { - n += 1 + sovProfiles(uint64(m.KeyStrindex)) - } - if m.StrStrindex != 0 { - n += 1 + sovProfiles(uint64(m.StrStrindex)) - } - if m.Num != 0 { - n += 1 + sovProfiles(uint64(m.Num)) - } - if m.NumUnitStrindex != 0 { - n += 1 + sovProfiles(uint64(m.NumUnitStrindex)) - } - return n -} - func (m *Mapping) Size() (n int) { if m == nil { return 0 @@ -3836,40 +3699,6 @@ func (m *Profile) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 18: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Attributes", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProfiles - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthProfiles - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthProfiles - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Attributes = append(m.Attributes, v11.KeyValue{}) - if err := m.Attributes[len(m.Attributes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex case 19: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field DroppedAttributesCount", wireType) @@ -3955,6 +3784,82 @@ func (m *Profile) Unmarshal(dAtA []byte) error { m.OriginalPayload = []byte{} } iNdEx = postIndex + case 22: + if wireType == 0 { + var v int32 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProfiles + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.AttributeIndices = append(m.AttributeIndices, v) + } else if wireType == 2 { + var packedLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProfiles + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + packedLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if packedLen < 0 { + return ErrInvalidLengthProfiles + } + postIndex := iNdEx + packedLen + if postIndex < 0 { + return ErrInvalidLengthProfiles + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + var elementCount int + var count int + for _, integer := range dAtA[iNdEx:postIndex] { + if integer < 128 { + count++ + } + } + elementCount = count + if elementCount != 0 && len(m.AttributeIndices) == 0 { + m.AttributeIndices = make([]int32, 0, elementCount) + } + for iNdEx < postIndex { + var v int32 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProfiles + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.AttributeIndices = append(m.AttributeIndices, v) + } + } else { + return fmt.Errorf("proto: wrong wireType = %d for field AttributeIndices", wireType) + } default: iNdEx = preIndex skippy, err := skipProfiles(dAtA[iNdEx:]) @@ -4623,132 +4528,6 @@ func (m *Sample) Unmarshal(dAtA []byte) error { } return nil } -func (m *Label) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProfiles - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: Label: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Label: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field KeyStrindex", wireType) - } - m.KeyStrindex = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProfiles - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.KeyStrindex |= int32(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field StrStrindex", wireType) - } - m.StrStrindex = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProfiles - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.StrStrindex |= int32(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Num", wireType) - } - m.Num = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProfiles - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Num |= int64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field NumUnitStrindex", wireType) - } - m.NumUnitStrindex = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProfiles - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.NumUnitStrindex |= int32(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipProfiles(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthProfiles - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func (m *Mapping) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1/trace.pb.go b/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1/trace.pb.go index c1fcf0764e..b0bddfb985 100644 --- a/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1/trace.pb.go +++ b/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1/trace.pb.go @@ -235,7 +235,8 @@ type ResourceSpans struct { // A list of ScopeSpans that originate from a resource. ScopeSpans []*ScopeSpans `protobuf:"bytes,2,rep,name=scope_spans,json=scopeSpans,proto3" json:"scope_spans,omitempty"` // The Schema URL, if known. This is the identifier of the Schema that the resource data - // is recorded in. To learn more about Schema URL see + // is recorded in. Notably, the last part of the URL path is the version number of the + // schema: http[s]://server[:port]/path/. To learn more about Schema URL see // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to the data in the "resource" field. It does not apply // to the data in the "scope_spans" field which have their own schema_url field. @@ -312,7 +313,8 @@ type ScopeSpans struct { // A list of Spans that originate from an instrumentation scope. Spans []*Span `protobuf:"bytes,2,rep,name=spans,proto3" json:"spans,omitempty"` // The Schema URL, if known. This is the identifier of the Schema that the span data - // is recorded in. To learn more about Schema URL see + // is recorded in. Notably, the last part of the URL path is the version number of the + // schema: http[s]://server[:port]/path/. To learn more about Schema URL see // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to all spans and span events in the "spans" field. SchemaUrl string `protobuf:"bytes,3,opt,name=schema_url,json=schemaUrl,proto3" json:"schema_url,omitempty"` diff --git a/vendor/go.opentelemetry.io/otel/CHANGELOG.md b/vendor/go.opentelemetry.io/otel/CHANGELOG.md index a30988f25d..599d59cd13 100644 --- a/vendor/go.opentelemetry.io/otel/CHANGELOG.md +++ b/vendor/go.opentelemetry.io/otel/CHANGELOG.md @@ -8,6 +8,21 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [Unreleased] + + + +## [1.34.0/0.56.0/0.10.0] 2025-01-17 + +### Changed + +- Remove the notices from `Logger` to make the whole Logs API user-facing in `go.opentelemetry.io/otel/log`. (#6167) + +### Fixed + +- Relax minimum Go version to 1.22.0 in various modules. (#6073) +- The `Type` name logged for the `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc` client is corrected from `otlphttpgrpc` to `otlptracegrpc`. (#6143) +- The `Type` name logged for the `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlphttpgrpc` client is corrected from `otlphttphttp` to `otlptracehttp`. (#6143) + ## [1.33.0/0.55.0/0.9.0/0.0.12] 2024-12-12 ### Added @@ -37,9 +52,6 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Fix attribute value truncation in `go.opentelemetry.io/otel/sdk/trace`. (#5997) - Fix attribute value truncation in `go.opentelemetry.io/otel/sdk/log`. (#6032) - - - ## [1.32.0/0.54.0/0.8.0/0.0.11] 2024-11-08 ### Added @@ -3185,7 +3197,8 @@ It contains api and sdk for trace and meter. - CircleCI build CI manifest files. - CODEOWNERS file to track owners of this project. -[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.33.0...HEAD +[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.34.0...HEAD +[1.34.0/0.56.0/0.10.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.34.0 [1.33.0/0.55.0/0.9.0/0.0.12]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.33.0 [1.32.0/0.54.0/0.8.0/0.0.11]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.32.0 [1.31.0/0.53.0/0.7.0/0.0.10]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.31.0 diff --git a/vendor/go.opentelemetry.io/otel/README.md b/vendor/go.opentelemetry.io/otel/README.md index efec278905..d9a1920762 100644 --- a/vendor/go.opentelemetry.io/otel/README.md +++ b/vendor/go.opentelemetry.io/otel/README.md @@ -1,6 +1,6 @@ # OpenTelemetry-Go -[![CI](https://github.com/open-telemetry/opentelemetry-go/workflows/ci/badge.svg)](https://github.com/open-telemetry/opentelemetry-go/actions?query=workflow%3Aci+branch%3Amain) +[![ci](https://github.com/open-telemetry/opentelemetry-go/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/open-telemetry/opentelemetry-go/actions/workflows/ci.yml) [![codecov.io](https://codecov.io/gh/open-telemetry/opentelemetry-go/coverage.svg?branch=main)](https://app.codecov.io/gh/open-telemetry/opentelemetry-go?branch=main) [![PkgGoDev](https://pkg.go.dev/badge/go.opentelemetry.io/otel)](https://pkg.go.dev/go.opentelemetry.io/otel) [![Go Report Card](https://goreportcard.com/badge/go.opentelemetry.io/otel)](https://goreportcard.com/report/go.opentelemetry.io/otel) diff --git a/vendor/go.opentelemetry.io/otel/RELEASING.md b/vendor/go.opentelemetry.io/otel/RELEASING.md index ffa9b61258..4ebef4f9dd 100644 --- a/vendor/go.opentelemetry.io/otel/RELEASING.md +++ b/vendor/go.opentelemetry.io/otel/RELEASING.md @@ -130,6 +130,6 @@ Importantly, bump any package versions referenced to be the latest one you just Bump the dependencies in the following Go services: -- [`accountingservice`](https://github.com/open-telemetry/opentelemetry-demo/tree/main/src/accountingservice) -- [`checkoutservice`](https://github.com/open-telemetry/opentelemetry-demo/tree/main/src/checkoutservice) -- [`productcatalogservice`](https://github.com/open-telemetry/opentelemetry-demo/tree/main/src/productcatalogservice) +- [`accounting`](https://github.com/open-telemetry/opentelemetry-demo/tree/main/src/accounting) +- [`checkoutservice`](https://github.com/open-telemetry/opentelemetry-demo/tree/main/src/checkout) +- [`productcatalogservice`](https://github.com/open-telemetry/opentelemetry-demo/tree/main/src/product-catalog) diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/client.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/client.go index 2171bee3c8..8409b5f8f9 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/client.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/client.go @@ -294,7 +294,7 @@ func (c *client) MarshalLog() interface{} { Type string Endpoint string }{ - Type: "otlphttpgrpc", + Type: "otlptracegrpc", Endpoint: c.endpoint, } } diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/version.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/version.go index 8ea156a098..f156ee6672 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/version.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/version.go @@ -5,5 +5,5 @@ package otlptrace // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace" // Version is the current release version of the OpenTelemetry OTLP trace exporter in use. func Version() string { - return "1.33.0" + return "1.34.0" } diff --git a/vendor/go.opentelemetry.io/otel/renovate.json b/vendor/go.opentelemetry.io/otel/renovate.json index 0a29a2f13d..4f80c898a1 100644 --- a/vendor/go.opentelemetry.io/otel/renovate.json +++ b/vendor/go.opentelemetry.io/otel/renovate.json @@ -14,12 +14,6 @@ "matchDepTypes": ["indirect"], "enabled": true }, - { - "matchFileNames": ["internal/tools/**"], - "matchManagers": ["gomod"], - "matchDepTypes": ["indirect"], - "enabled": false - }, { "matchPackageNames": ["google.golang.org/genproto/googleapis/**"], "groupName": "googleapis" diff --git a/vendor/go.opentelemetry.io/otel/sdk/version.go b/vendor/go.opentelemetry.io/otel/sdk/version.go index ba7db48895..6b40385107 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/version.go +++ b/vendor/go.opentelemetry.io/otel/sdk/version.go @@ -5,5 +5,5 @@ package sdk // import "go.opentelemetry.io/otel/sdk" // Version is the current release version of the OpenTelemetry SDK in use. func Version() string { - return "1.33.0" + return "1.34.0" } diff --git a/vendor/go.opentelemetry.io/otel/version.go b/vendor/go.opentelemetry.io/otel/version.go index fb7d12673e..eb22002d82 100644 --- a/vendor/go.opentelemetry.io/otel/version.go +++ b/vendor/go.opentelemetry.io/otel/version.go @@ -5,5 +5,5 @@ package otel // import "go.opentelemetry.io/otel" // Version is the current release version of OpenTelemetry in use. func Version() string { - return "1.33.0" + return "1.34.0" } diff --git a/vendor/go.opentelemetry.io/otel/versions.yaml b/vendor/go.opentelemetry.io/otel/versions.yaml index 9f878cd1fe..ce4fe59b0e 100644 --- a/vendor/go.opentelemetry.io/otel/versions.yaml +++ b/vendor/go.opentelemetry.io/otel/versions.yaml @@ -3,7 +3,7 @@ module-sets: stable-v1: - version: v1.33.0 + version: v1.34.0 modules: - go.opentelemetry.io/otel - go.opentelemetry.io/otel/bridge/opencensus @@ -23,11 +23,11 @@ module-sets: - go.opentelemetry.io/otel/sdk/metric - go.opentelemetry.io/otel/trace experimental-metrics: - version: v0.55.0 + version: v0.56.0 modules: - go.opentelemetry.io/otel/exporters/prometheus experimental-logs: - version: v0.9.0 + version: v0.10.0 modules: - go.opentelemetry.io/otel/log - go.opentelemetry.io/otel/sdk/log diff --git a/vendor/go.opentelemetry.io/proto/otlp/trace/v1/trace.pb.go b/vendor/go.opentelemetry.io/proto/otlp/trace/v1/trace.pb.go index d7099c35bc..b342a0a940 100644 --- a/vendor/go.opentelemetry.io/proto/otlp/trace/v1/trace.pb.go +++ b/vendor/go.opentelemetry.io/proto/otlp/trace/v1/trace.pb.go @@ -311,7 +311,8 @@ type ResourceSpans struct { // A list of ScopeSpans that originate from a resource. ScopeSpans []*ScopeSpans `protobuf:"bytes,2,rep,name=scope_spans,json=scopeSpans,proto3" json:"scope_spans,omitempty"` // The Schema URL, if known. This is the identifier of the Schema that the resource data - // is recorded in. To learn more about Schema URL see + // is recorded in. Notably, the last part of the URL path is the version number of the + // schema: http[s]://server[:port]/path/. To learn more about Schema URL see // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to the data in the "resource" field. It does not apply // to the data in the "scope_spans" field which have their own schema_url field. @@ -384,7 +385,8 @@ type ScopeSpans struct { // A list of Spans that originate from an instrumentation scope. Spans []*Span `protobuf:"bytes,2,rep,name=spans,proto3" json:"spans,omitempty"` // The Schema URL, if known. This is the identifier of the Schema that the span data - // is recorded in. To learn more about Schema URL see + // is recorded in. Notably, the last part of the URL path is the version number of the + // schema: http[s]://server[:port]/path/. To learn more about Schema URL see // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to all spans and span events in the "spans" field. SchemaUrl string `protobuf:"bytes,3,opt,name=schema_url,json=schemaUrl,proto3" json:"schema_url,omitempty"` diff --git a/vendor/golang.org/x/crypto/pkcs12/crypto.go b/vendor/golang.org/x/crypto/pkcs12/crypto.go index 96f4a1a56e..212538cb5a 100644 --- a/vendor/golang.org/x/crypto/pkcs12/crypto.go +++ b/vendor/golang.org/x/crypto/pkcs12/crypto.go @@ -26,7 +26,7 @@ type pbeCipher interface { create(key []byte) (cipher.Block, error) // deriveKey returns a key derived from the given password and salt. deriveKey(salt, password []byte, iterations int) []byte - // deriveKey returns an IV derived from the given password and salt. + // deriveIV returns an IV derived from the given password and salt. deriveIV(salt, password []byte, iterations int) []byte } diff --git a/vendor/golang.org/x/net/http2/config.go b/vendor/golang.org/x/net/http2/config.go index de58dfb8dc..ca645d9a1a 100644 --- a/vendor/golang.org/x/net/http2/config.go +++ b/vendor/golang.org/x/net/http2/config.go @@ -60,7 +60,7 @@ func configFromServer(h1 *http.Server, h2 *Server) http2Config { return conf } -// configFromServer merges configuration settings from h2 and h2.t1.HTTP2 +// configFromTransport merges configuration settings from h2 and h2.t1.HTTP2 // (the net/http Transport). func configFromTransport(h2 *Transport) http2Config { conf := http2Config{ diff --git a/vendor/golang.org/x/net/http2/config_go124.go b/vendor/golang.org/x/net/http2/config_go124.go index e3784123c8..5b516c55ff 100644 --- a/vendor/golang.org/x/net/http2/config_go124.go +++ b/vendor/golang.org/x/net/http2/config_go124.go @@ -13,7 +13,7 @@ func fillNetHTTPServerConfig(conf *http2Config, srv *http.Server) { fillNetHTTPConfig(conf, srv.HTTP2) } -// fillNetHTTPServerConfig sets fields in conf from tr.HTTP2. +// fillNetHTTPTransportConfig sets fields in conf from tr.HTTP2. func fillNetHTTPTransportConfig(conf *http2Config, tr *http.Transport) { fillNetHTTPConfig(conf, tr.HTTP2) } diff --git a/vendor/golang.org/x/net/http2/transport.go b/vendor/golang.org/x/net/http2/transport.go index 090d0e1bdb..b2e2ed3373 100644 --- a/vendor/golang.org/x/net/http2/transport.go +++ b/vendor/golang.org/x/net/http2/transport.go @@ -375,6 +375,7 @@ type ClientConn struct { doNotReuse bool // whether conn is marked to not be reused for any future requests closing bool closed bool + closedOnIdle bool // true if conn was closed for idleness seenSettings bool // true if we've seen a settings frame, false otherwise seenSettingsChan chan struct{} // closed when seenSettings is true or frame reading fails wantSettingsAck bool // we sent a SETTINGS frame and haven't heard back @@ -1089,10 +1090,12 @@ func (cc *ClientConn) idleStateLocked() (st clientConnIdleState) { // If this connection has never been used for a request and is closed, // then let it take a request (which will fail). + // If the conn was closed for idleness, we're racing the idle timer; + // don't try to use the conn. (Issue #70515.) // // This avoids a situation where an error early in a connection's lifetime // goes unreported. - if cc.nextStreamID == 1 && cc.streamsReserved == 0 && cc.closed { + if cc.nextStreamID == 1 && cc.streamsReserved == 0 && cc.closed && !cc.closedOnIdle { st.canTakeNewRequest = true } @@ -1155,6 +1158,7 @@ func (cc *ClientConn) closeIfIdle() { return } cc.closed = true + cc.closedOnIdle = true nextID := cc.nextStreamID // TODO: do clients send GOAWAY too? maybe? Just Close: cc.mu.Unlock() @@ -2434,9 +2438,12 @@ func (rl *clientConnReadLoop) cleanup() { // 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 + unusedWaitTime := 5 * time.Second + if cc.idleTimeout > 0 && unusedWaitTime > cc.idleTimeout { + unusedWaitTime = cc.idleTimeout + } idleTime := cc.t.now().Sub(cc.lastActive) - if atomic.LoadUint32(&cc.atomicReused) == 0 && idleTime < unusedWaitTime { + if atomic.LoadUint32(&cc.atomicReused) == 0 && idleTime < unusedWaitTime && !cc.closedOnIdle { cc.idleTimer = cc.t.afterFunc(unusedWaitTime-idleTime, func() { cc.t.connPool().MarkDead(cc) }) diff --git a/vendor/golang.org/x/sys/unix/syscall_dragonfly.go b/vendor/golang.org/x/sys/unix/syscall_dragonfly.go index 97cb916f2c..be8c002070 100644 --- a/vendor/golang.org/x/sys/unix/syscall_dragonfly.go +++ b/vendor/golang.org/x/sys/unix/syscall_dragonfly.go @@ -246,6 +246,18 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e return sendfile(outfd, infd, offset, count) } +func Dup3(oldfd, newfd, flags int) error { + if oldfd == newfd || flags&^O_CLOEXEC != 0 { + return EINVAL + } + how := F_DUP2FD + if flags&O_CLOEXEC != 0 { + how = F_DUP2FD_CLOEXEC + } + _, err := fcntl(oldfd, how, newfd) + return err +} + /* * Exposed directly */ diff --git a/vendor/golang.org/x/sys/windows/dll_windows.go b/vendor/golang.org/x/sys/windows/dll_windows.go index 4e613cf633..3ca814f54d 100644 --- a/vendor/golang.org/x/sys/windows/dll_windows.go +++ b/vendor/golang.org/x/sys/windows/dll_windows.go @@ -43,8 +43,8 @@ type DLL struct { // LoadDLL loads DLL file into memory. // // Warning: using LoadDLL without an absolute path name is subject to -// DLL preloading attacks. To safely load a system DLL, use LazyDLL -// with System set to true, or use LoadLibraryEx directly. +// DLL preloading attacks. To safely load a system DLL, use [NewLazySystemDLL], +// or use [LoadLibraryEx] directly. func LoadDLL(name string) (dll *DLL, err error) { namep, err := UTF16PtrFromString(name) if err != nil { @@ -271,6 +271,9 @@ func (d *LazyDLL) NewProc(name string) *LazyProc { } // NewLazyDLL creates new LazyDLL associated with DLL file. +// +// Warning: using NewLazyDLL without an absolute path name is subject to +// DLL preloading attacks. To safely load a system DLL, use [NewLazySystemDLL]. func NewLazyDLL(name string) *LazyDLL { return &LazyDLL{Name: name} } @@ -410,7 +413,3 @@ func loadLibraryEx(name string, system bool) (*DLL, error) { } return &DLL{Name: name, Handle: h}, nil } - -type errString string - -func (s errString) Error() string { return string(s) } diff --git a/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go b/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go index 137cc8df1d..65fe2628e9 100644 --- a/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go +++ b/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go @@ -2,22 +2,64 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package gcexportdata provides functions for locating, reading, and -// writing export data files containing type information produced by the -// gc compiler. This package supports go1.7 export data format and all -// later versions. -// -// Although it might seem convenient for this package to live alongside -// go/types in the standard library, this would cause version skew -// problems for developer tools that use it, since they must be able to -// consume the outputs of the gc compiler both before and after a Go -// update such as from Go 1.7 to Go 1.8. Because this package lives in -// golang.org/x/tools, sites can update their version of this repo some -// time before the Go 1.8 release and rebuild and redeploy their -// developer tools, which will then be able to consume both Go 1.7 and -// Go 1.8 export data files, so they will work before and after the -// Go update. (See discussion at https://golang.org/issue/15651.) -package gcexportdata // import "golang.org/x/tools/go/gcexportdata" +// Package gcexportdata provides functions for reading and writing +// export data, which is a serialized description of the API of a Go +// package including the names, kinds, types, and locations of all +// exported declarations. +// +// The standard Go compiler (cmd/compile) writes an export data file +// for each package it compiles, which it later reads when compiling +// packages that import the earlier one. The compiler must thus +// contain logic to both write and read export data. +// (See the "Export" section in the cmd/compile/README file.) +// +// The [Read] function in this package can read files produced by the +// compiler, producing [go/types] data structures. As a matter of +// policy, Read supports export data files produced by only the last +// two Go releases plus tip; see https://go.dev/issue/68898. The +// export data files produced by the compiler contain additional +// details related to generics, inlining, and other optimizations that +// cannot be decoded by the [Read] function. +// +// In files written by the compiler, the export data is not at the +// start of the file. Before calling Read, use [NewReader] to locate +// the desired portion of the file. +// +// The [Write] function in this package encodes the exported API of a +// Go package ([types.Package]) as a file. Such files can be later +// decoded by Read, but cannot be consumed by the compiler. +// +// # Future changes +// +// Although Read supports the formats written by both Write and the +// compiler, the two are quite different, and there is an open +// proposal (https://go.dev/issue/69491) to separate these APIs. +// +// Under that proposal, this package would ultimately provide only the +// Read operation for compiler export data, which must be defined in +// this module (golang.org/x/tools), not in the standard library, to +// avoid version skew for developer tools that need to read compiler +// export data both before and after a Go release, such as from Go +// 1.23 to Go 1.24. Because this package lives in the tools module, +// clients can update their version of the module some time before the +// Go 1.24 release and rebuild and redeploy their tools, which will +// then be able to consume both Go 1.23 and Go 1.24 export data files, +// so they will work before and after the Go update. (See discussion +// at https://go.dev/issue/15651.) +// +// The operations to import and export [go/types] data structures +// would be defined in the go/types package as Import and Export. +// [Write] would (eventually) delegate to Export, +// and [Read], when it detects a file produced by Export, +// would delegate to Import. +// +// # Deprecations +// +// The [NewImporter] and [Find] functions are deprecated and should +// not be used in new code. The [WriteBundle] and [ReadBundle] +// functions are experimental, and there is an open proposal to +// deprecate them (https://go.dev/issue/69573). +package gcexportdata import ( "bufio" @@ -64,24 +106,18 @@ func Find(importPath, srcDir string) (filename, path string) { // additional trailing data beyond the end of the export data. func NewReader(r io.Reader) (io.Reader, error) { buf := bufio.NewReader(r) - _, size, err := gcimporter.FindExportData(buf) + size, err := gcimporter.FindExportData(buf) if err != nil { return nil, err } - if size >= 0 { - // We were given an archive and found the __.PKGDEF in it. - // This tells us the size of the export data, and we don't - // need to return the entire file. - return &io.LimitedReader{ - R: buf, - N: size, - }, nil - } else { - // We were given an object file. As such, we don't know how large - // the export data is and must return the entire file. - return buf, nil - } + // We were given an archive and found the __.PKGDEF in it. + // This tells us the size of the export data, and we don't + // need to return the entire file. + return &io.LimitedReader{ + R: buf, + N: size, + }, nil } // readAll works the same way as io.ReadAll, but avoids allocations and copies @@ -100,6 +136,11 @@ func readAll(r io.Reader) ([]byte, error) { // Read reads export data from in, decodes it, and returns type // information for the package. // +// Read is capable of reading export data produced by [Write] at the +// same source code version, or by the last two Go releases (plus tip) +// of the standard Go compiler. Reading files from older compilers may +// produce an error. +// // The package path (effectively its linker symbol prefix) is // specified by path, since unlike the package name, this information // may not be recorded in the export data. @@ -128,14 +169,26 @@ func Read(in io.Reader, fset *token.FileSet, imports map[string]*types.Package, // (from "version"). Select appropriate importer. if len(data) > 0 { switch data[0] { - case 'v', 'c', 'd': // binary, till go1.10 + case 'v', 'c', 'd': + // binary, produced by cmd/compile till go1.10 return nil, fmt.Errorf("binary (%c) import format is no longer supported", data[0]) - case 'i': // indexed, till go1.19 + case 'i': + // indexed, produced by cmd/compile till go1.19, + // and also by [Write]. + // + // If proposal #69491 is accepted, go/types + // serialization will be implemented by + // types.Export, to which Write would eventually + // delegate (explicitly dropping any pretence at + // inter-version Write-Read compatibility). + // This [Read] function would delegate to types.Import + // when it detects that the file was produced by Export. _, pkg, err := gcimporter.IImportData(fset, imports, data[1:], path) return pkg, err - case 'u': // unified, from go1.20 + case 'u': + // unified, produced by cmd/compile since go1.20 _, pkg, err := gcimporter.UImportData(fset, imports, data[1:], path) return pkg, err diff --git a/vendor/golang.org/x/tools/go/packages/doc.go b/vendor/golang.org/x/tools/go/packages/doc.go index 3531ac8f5f..f1931d10ee 100644 --- a/vendor/golang.org/x/tools/go/packages/doc.go +++ b/vendor/golang.org/x/tools/go/packages/doc.go @@ -64,7 +64,7 @@ graph using the Imports fields. The Load function can be configured by passing a pointer to a Config as the first argument. A nil Config is equivalent to the zero Config, which -causes Load to run in LoadFiles mode, collecting minimal information. +causes Load to run in [LoadFiles] mode, collecting minimal information. See the documentation for type Config for details. As noted earlier, the Config.Mode controls the amount of detail @@ -72,14 +72,14 @@ reported about the loaded packages. See the documentation for type LoadMode for details. Most tools should pass their command-line arguments (after any flags) -uninterpreted to [Load], so that it can interpret them +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 +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. @@ -97,6 +97,15 @@ 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'.) + +The value of the PWD environment variable seen by the driver process +is the preferred name of its working directory. (The working directory +may have other aliases due to symbolic links; see the comment on the +Dir field of [exec.Cmd] for related information.) +When the driver process emits in its response the name of a file +that is a descendant of this directory, it must use an absolute path +that has the value of PWD as a prefix, to ensure that the returned +filenames satisfy the original query. */ package packages // import "golang.org/x/tools/go/packages" diff --git a/vendor/golang.org/x/tools/go/packages/external.go b/vendor/golang.org/x/tools/go/packages/external.go index c2b4b711b5..91bd62e83b 100644 --- a/vendor/golang.org/x/tools/go/packages/external.go +++ b/vendor/golang.org/x/tools/go/packages/external.go @@ -13,6 +13,7 @@ import ( "fmt" "os" "os/exec" + "slices" "strings" ) @@ -79,10 +80,10 @@ type DriverResponse struct { // 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) +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." +// the build system package structure, or "" if not found. // If GOPACKAGESDRIVER is set in the environment findExternalTool returns its // value, otherwise it searches for a binary named gopackagesdriver on the PATH. func findExternalDriver(cfg *Config) driver { @@ -103,7 +104,7 @@ func findExternalDriver(cfg *Config) driver { return nil } } - return func(cfg *Config, words ...string) (*DriverResponse, error) { + return func(cfg *Config, patterns []string) (*DriverResponse, error) { req, err := json.Marshal(DriverRequest{ Mode: cfg.Mode, Env: cfg.Env, @@ -117,7 +118,7 @@ func findExternalDriver(cfg *Config) driver { buf := new(bytes.Buffer) stderr := new(bytes.Buffer) - cmd := exec.CommandContext(cfg.Context, tool, words...) + cmd := exec.CommandContext(cfg.Context, tool, patterns...) cmd.Dir = cfg.Dir // The cwd gets resolved to the real path. On Darwin, where // /tmp is a symlink, this breaks anything that expects the @@ -131,7 +132,7 @@ func findExternalDriver(cfg *Config) driver { // command. // // (See similar trick in Invocation.run in ../../internal/gocommand/invoke.go) - cmd.Env = append(slicesClip(cfg.Env), "PWD="+cfg.Dir) + cmd.Env = append(slices.Clip(cfg.Env), "PWD="+cfg.Dir) cmd.Stdin = bytes.NewReader(req) cmd.Stdout = buf cmd.Stderr = stderr @@ -150,7 +151,3 @@ func findExternalDriver(cfg *Config) driver { 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 1a3a5b44f5..870271ed51 100644 --- a/vendor/golang.org/x/tools/go/packages/golist.go +++ b/vendor/golang.org/x/tools/go/packages/golist.go @@ -80,6 +80,12 @@ type golistState struct { cfg *Config ctx context.Context + runner *gocommand.Runner + + // overlay is the JSON file that encodes the Config.Overlay + // mapping, used by 'go list -overlay=...'. + overlay string + envOnce sync.Once goEnvError error goEnv map[string]string @@ -127,7 +133,10 @@ 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, err error) { +// +// overlay is the JSON file that encodes the cfg.Overlay +// mapping, used by 'go list -overlay=...' +func goListDriver(cfg *Config, runner *gocommand.Runner, overlay string, patterns []string) (_ *DriverResponse, err error) { // Make sure that any asynchronous go commands are killed when we return. parentCtx := cfg.Context if parentCtx == nil { @@ -142,13 +151,15 @@ func goListDriver(cfg *Config, patterns ...string) (_ *DriverResponse, err error cfg: cfg, ctx: ctx, vendorDirs: map[string]bool{}, + overlay: overlay, + runner: runner, } // Fill in response.Sizes asynchronously if necessary. - if cfg.Mode&NeedTypesSizes != 0 || cfg.Mode&NeedTypes != 0 { + if cfg.Mode&NeedTypesSizes != 0 || cfg.Mode&(NeedTypes|NeedTypesInfo) != 0 { errCh := make(chan error) go func() { - compiler, arch, err := getSizesForArgs(ctx, state.cfgInvocation(), cfg.gocmdRunner) + compiler, arch, err := getSizesForArgs(ctx, state.cfgInvocation(), runner) response.dr.Compiler = compiler response.dr.Arch = arch errCh <- err @@ -494,13 +505,14 @@ func (state *golistState) createDriverResponse(words ...string) (*DriverResponse pkg := &Package{ Name: p.Name, ID: p.ImportPath, + Dir: p.Dir, GoFiles: absJoin(p.Dir, p.GoFiles, p.CgoFiles), CompiledGoFiles: absJoin(p.Dir, p.CompiledGoFiles), OtherFiles: absJoin(p.Dir, otherFiles(p)...), EmbedFiles: absJoin(p.Dir, p.EmbedFiles), EmbedPatterns: absJoin(p.Dir, p.EmbedPatterns), IgnoredFiles: absJoin(p.Dir, p.IgnoredGoFiles, p.IgnoredOtherFiles), - forTest: p.ForTest, + ForTest: p.ForTest, depsErrors: p.DepsErrors, Module: p.Module, } @@ -681,7 +693,7 @@ func (state *golistState) shouldAddFilenameFromError(p *jsonPackage) bool { // getGoVersion returns the effective minor version of the go command. func (state *golistState) getGoVersion() (int, error) { state.goVersionOnce.Do(func() { - state.goVersion, state.goVersionError = gocommand.GoVersion(state.ctx, state.cfgInvocation(), state.cfg.gocmdRunner) + state.goVersion, state.goVersionError = gocommand.GoVersion(state.ctx, state.cfgInvocation(), state.runner) }) return state.goVersion, state.goVersionError } @@ -751,7 +763,7 @@ func jsonFlag(cfg *Config, goVersion int) string { } } addFields("Name", "ImportPath", "Error") // These fields are always needed - if cfg.Mode&NeedFiles != 0 || cfg.Mode&NeedTypes != 0 { + if cfg.Mode&NeedFiles != 0 || cfg.Mode&(NeedTypes|NeedTypesInfo) != 0 { addFields("Dir", "GoFiles", "IgnoredGoFiles", "IgnoredOtherFiles", "CFiles", "CgoFiles", "CXXFiles", "MFiles", "HFiles", "FFiles", "SFiles", "SwigFiles", "SwigCXXFiles", "SysoFiles") @@ -759,7 +771,7 @@ func jsonFlag(cfg *Config, goVersion int) string { addFields("TestGoFiles", "XTestGoFiles") } } - if cfg.Mode&NeedTypes != 0 { + if cfg.Mode&(NeedTypes|NeedTypesInfo) != 0 { // CompiledGoFiles seems to be required for the test case TestCgoNoSyntax, // even when -compiled isn't passed in. // TODO(#52435): Should we make the test ask for -compiled, or automatically @@ -784,7 +796,7 @@ func jsonFlag(cfg *Config, goVersion int) string { // Request Dir in the unlikely case Export is not absolute. addFields("Dir", "Export") } - if cfg.Mode&needInternalForTest != 0 { + if cfg.Mode&NeedForTest != 0 { addFields("ForTest") } if cfg.Mode&needInternalDepsErrors != 0 { @@ -840,7 +852,7 @@ func (state *golistState) cfgInvocation() gocommand.Invocation { Env: cfg.Env, Logf: cfg.Logf, WorkingDir: cfg.Dir, - Overlay: cfg.goListOverlayFile, + Overlay: state.overlay, } } @@ -851,11 +863,8 @@ func (state *golistState) invokeGo(verb string, args ...string) (*bytes.Buffer, inv := state.cfgInvocation() inv.Verb = verb inv.Args = args - gocmdRunner := cfg.gocmdRunner - if gocmdRunner == nil { - gocmdRunner = &gocommand.Runner{} - } - stdout, stderr, friendlyErr, err := gocmdRunner.RunRaw(cfg.Context, inv) + + stdout, stderr, friendlyErr, err := state.runner.RunRaw(cfg.Context, inv) if err != nil { // Check for 'go' executable not being found. if ee, ok := err.(*exec.Error); ok && ee.Err == exec.ErrNotFound { @@ -879,6 +888,12 @@ func (state *golistState) invokeGo(verb string, args ...string) (*bytes.Buffer, return nil, friendlyErr } + // Return an error if 'go list' failed due to missing tools in + // $GOROOT/pkg/tool/$GOOS_$GOARCH (#69606). + if len(stderr.String()) > 0 && strings.Contains(stderr.String(), `go: no such tool`) { + return nil, friendlyErr + } + // Is there an error running the C compiler in cgo? This will be reported in the "Error" field // and should be suppressed by go list -e. // diff --git a/vendor/golang.org/x/tools/go/packages/loadmode_string.go b/vendor/golang.org/x/tools/go/packages/loadmode_string.go index 5c080d21b5..969da4c263 100644 --- a/vendor/golang.org/x/tools/go/packages/loadmode_string.go +++ b/vendor/golang.org/x/tools/go/packages/loadmode_string.go @@ -9,49 +9,47 @@ import ( "strings" ) -var allModes = []LoadMode{ - NeedName, - NeedFiles, - NeedCompiledGoFiles, - NeedImports, - NeedDeps, - NeedExportFile, - NeedTypes, - NeedSyntax, - NeedTypesInfo, - NeedTypesSizes, +var modes = [...]struct { + mode LoadMode + name string +}{ + {NeedName, "NeedName"}, + {NeedFiles, "NeedFiles"}, + {NeedCompiledGoFiles, "NeedCompiledGoFiles"}, + {NeedImports, "NeedImports"}, + {NeedDeps, "NeedDeps"}, + {NeedExportFile, "NeedExportFile"}, + {NeedTypes, "NeedTypes"}, + {NeedSyntax, "NeedSyntax"}, + {NeedTypesInfo, "NeedTypesInfo"}, + {NeedTypesSizes, "NeedTypesSizes"}, + {NeedForTest, "NeedForTest"}, + {NeedModule, "NeedModule"}, + {NeedEmbedFiles, "NeedEmbedFiles"}, + {NeedEmbedPatterns, "NeedEmbedPatterns"}, } -var modeStrings = []string{ - "NeedName", - "NeedFiles", - "NeedCompiledGoFiles", - "NeedImports", - "NeedDeps", - "NeedExportFile", - "NeedTypes", - "NeedSyntax", - "NeedTypesInfo", - "NeedTypesSizes", -} - -func (mod LoadMode) String() string { - m := mod - if m == 0 { +func (mode LoadMode) String() string { + if mode == 0 { return "LoadMode(0)" } var out []string - for i, x := range allModes { - if x > m { - break + // named bits + for _, item := range modes { + if (mode & item.mode) != 0 { + mode ^= item.mode + out = append(out, item.name) } - if (m & x) != 0 { - out = append(out, modeStrings[i]) - m = m ^ x + } + // unnamed residue + if mode != 0 { + if out == nil { + return fmt.Sprintf("LoadMode(%#x)", int(mode)) } + out = append(out, fmt.Sprintf("%#x", int(mode))) } - if m != 0 { - out = append(out, "Unknown") + if len(out) == 1 { + return out[0] } - return fmt.Sprintf("LoadMode(%s)", strings.Join(out, "|")) + return "(" + strings.Join(out, "|") + ")" } diff --git a/vendor/golang.org/x/tools/go/packages/packages.go b/vendor/golang.org/x/tools/go/packages/packages.go index 0b6bfaff80..9dedf9777d 100644 --- a/vendor/golang.org/x/tools/go/packages/packages.go +++ b/vendor/golang.org/x/tools/go/packages/packages.go @@ -16,13 +16,13 @@ import ( "go/scanner" "go/token" "go/types" - "io" "log" "os" "path/filepath" "runtime" "strings" "sync" + "sync/atomic" "time" "golang.org/x/sync/errgroup" @@ -31,7 +31,6 @@ import ( "golang.org/x/tools/internal/gocommand" "golang.org/x/tools/internal/packagesinternal" "golang.org/x/tools/internal/typesinternal" - "golang.org/x/tools/internal/versions" ) // A LoadMode controls the amount of detail to return when loading. @@ -44,19 +43,33 @@ import ( // ID and Errors (if present) will always be filled. // [Load] may return more information than requested. // +// The Mode flag is a union of several bits named NeedName, +// NeedFiles, and so on, each of which determines whether +// a given field of Package (Name, Files, etc) should be +// populated. +// +// For convenience, we provide named constants for the most +// common combinations of Need flags: +// +// [LoadFiles] lists of files in each package +// [LoadImports] ... plus imports +// [LoadTypes] ... plus type information +// [LoadSyntax] ... plus type-annotated syntax +// [LoadAllSyntax] ... for all dependencies +// // Unfortunately there are a number of open bugs related to // interactions among the LoadMode bits: -// - 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 +// - 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 ( // NeedName adds Name and PkgPath. NeedName LoadMode = 1 << iota - // NeedFiles adds GoFiles and OtherFiles. + // NeedFiles adds Dir, GoFiles, OtherFiles, and IgnoredFiles NeedFiles // NeedCompiledGoFiles adds CompiledGoFiles. @@ -78,7 +91,7 @@ const ( // NeedSyntax adds Syntax and Fset. NeedSyntax - // NeedTypesInfo adds TypesInfo. + // NeedTypesInfo adds TypesInfo and Fset. NeedTypesInfo // NeedTypesSizes adds TypesSizes. @@ -87,9 +100,10 @@ const ( // needInternalDepsErrors adds the internal deps errors field for use by gopls. needInternalDepsErrors - // needInternalForTest adds the internal forTest field. + // NeedForTest adds ForTest. + // // Tests must also be set on the context for this field to be populated. - needInternalForTest + NeedForTest // typecheckCgo enables full support for type checking cgo. Requires Go 1.15+. // Modifies CompiledGoFiles and Types, and has no effect on its own. @@ -103,27 +117,24 @@ const ( // NeedEmbedPatterns adds EmbedPatterns. NeedEmbedPatterns + + // Be sure to update loadmode_string.go when adding new items! ) const ( - // Deprecated: LoadFiles exists for historical compatibility - // and should not be used. Please directly specify the needed fields using the Need values. + // LoadFiles loads the name and file names for the initial packages. LoadFiles = NeedName | NeedFiles | NeedCompiledGoFiles - // Deprecated: LoadImports exists for historical compatibility - // and should not be used. Please directly specify the needed fields using the Need values. + // LoadImports loads the name, file names, and import mapping for the initial packages. LoadImports = LoadFiles | NeedImports - // Deprecated: LoadTypes exists for historical compatibility - // and should not be used. Please directly specify the needed fields using the Need values. + // LoadTypes loads exported type information for the initial packages. LoadTypes = LoadImports | NeedTypes | NeedTypesSizes - // Deprecated: LoadSyntax exists for historical compatibility - // and should not be used. Please directly specify the needed fields using the Need values. + // LoadSyntax loads typed syntax for the initial packages. LoadSyntax = LoadTypes | NeedSyntax | NeedTypesInfo - // Deprecated: LoadAllSyntax exists for historical compatibility - // and should not be used. Please directly specify the needed fields using the Need values. + // LoadAllSyntax loads typed syntax for the initial packages and all dependencies. LoadAllSyntax = LoadSyntax | NeedDeps // Deprecated: NeedExportsFile is a historical misspelling of NeedExportFile. @@ -133,13 +144,7 @@ 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. +// Calls to [Load] do not modify this struct. type Config struct { // Mode controls the level of information returned for each package. Mode LoadMode @@ -170,19 +175,10 @@ type Config struct { // Env []string - // gocmdRunner guards go command calls from concurrency errors. - gocmdRunner *gocommand.Runner - // BuildFlags is a list of command-line flags to be passed through to // the build system's query tool. BuildFlags []string - // modFile will be used for -modfile in go command invocations. - modFile string - - // modFlag will be used for -modfile in go command invocations. - modFlag string - // Fset provides source position information for syntax trees and types. // If Fset is nil, Load will use a new fileset, but preserve Fset's value. Fset *token.FileSet @@ -229,21 +225,24 @@ type Config struct { // drivers may vary in their level of support for overlays. Overlay map[string][]byte - // goListOverlayFile is the JSON file that encodes the Overlay - // mapping, used by 'go list -overlay=...' - goListOverlayFile string + // -- Hidden configuration fields only for use in x/tools -- + + // modFile will be used for -modfile in go command invocations. + modFile string + + // modFlag will be used for -modfile in go command invocations. + modFlag string } // Load loads and returns the Go packages named by the given patterns. // -// Config specifies loading options; -// nil behaves the same as an empty Config. +// The cfg parameter specifies loading options; nil behaves the same as an empty [Config]. // // 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. +// [NeedName] | [NeedFiles] | [NeedCompiledGoFiles]. // // Each call to Load returns a new set of [Package] instances. // The Packages and their Imports form a directed acyclic graph. @@ -260,7 +259,7 @@ type Config struct { // Errors associated with a particular package are recorded in the // corresponding Package's Errors list, and do not cause Load to // return an error. Clients may need to handle such errors before -// proceeding with further analysis. The PrintErrors function is +// proceeding with further analysis. The [PrintErrors] function is // provided for convenient display of all errors. func Load(cfg *Config, patterns ...string) ([]*Package, error) { ld := newLoader(cfg) @@ -323,21 +322,24 @@ func defaultDriver(cfg *Config, patterns ...string) (*DriverResponse, bool, erro } else if !response.NotHandled { return response, true, nil } - // (fall through) + // not handled: fall through } // 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) + overlayFile, cleanupOverlay, err := gocommand.WriteOverlays(cfg.Overlay) if err != nil { return nil, false, err } defer cleanupOverlay() - cfg.goListOverlayFile = overlay - response, err := callDriverOnChunks(goListDriver, cfg, chunks) + var runner gocommand.Runner // (shared across many 'go list' calls) + driver := func(cfg *Config, patterns []string) (*DriverResponse, error) { + return goListDriver(cfg, &runner, overlayFile, patterns) + } + response, err := callDriverOnChunks(driver, cfg, chunks) if err != nil { return nil, false, err } @@ -375,16 +377,14 @@ func splitIntoChunks(patterns []string, argMax int) ([][]string, error) { func callDriverOnChunks(driver driver, cfg *Config, chunks [][]string) (*DriverResponse, error) { if len(chunks) == 0 { - return driver(cfg) + return driver(cfg, nil) } 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...) + responses[i], err = driver(cfg, chunk) if responses[i] != nil && responses[i].NotHandled { err = errNotHandled } @@ -434,6 +434,12 @@ type Package struct { // PkgPath is the package path as used by the go/types package. PkgPath string + // Dir is the directory associated with the package, if it exists. + // + // For packages listed by the go command, this is the directory containing + // the package files. + Dir string + // Errors contains any errors encountered querying the metadata // of the package, or while parsing or type-checking its files. Errors []Error @@ -521,8 +527,8 @@ type Package struct { // -- internal -- - // forTest is the package under test, if any. - forTest string + // 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 @@ -551,9 +557,6 @@ type ModuleError struct { } func init() { - packagesinternal.GetForTest = func(p interface{}) string { - return p.(*Package).forTest - } packagesinternal.GetDepsErrors = func(p interface{}) []*packagesinternal.PackageError { return p.(*Package).depsErrors } @@ -565,7 +568,6 @@ func init() { } packagesinternal.TypecheckCgo = int(typecheckCgo) packagesinternal.DepsErrors = int(needInternalDepsErrors) - packagesinternal.ForTest = int(needInternalForTest) } // An Error describes a problem with a package's metadata, syntax, or types. @@ -681,18 +683,19 @@ func (p *Package) String() string { return p.ID } // loaderPackage augments Package with state used during the loading phase type loaderPackage struct { *Package - importErrors map[string]error // maps each bad import to its error - loadOnce sync.Once - color uint8 // for cycle detection - needsrc bool // load from source (Mode >= LoadTypes) - needtypes bool // type information is either requested or depended on - initial bool // package was matched by a pattern - goVersion int // minor version number of go command on PATH + importErrors map[string]error // maps each bad import to its error + preds []*loaderPackage // packages that import this one + unfinishedSuccs atomic.Int32 // number of direct imports not yet loaded + color uint8 // for cycle detection + needsrc bool // load from source (Mode >= LoadTypes) + needtypes bool // type information is either requested or depended on + initial bool // package was matched by a pattern + goVersion int // minor version number of go command on PATH } // loader holds the working state of a single call to load. type loader struct { - pkgs map[string]*loaderPackage + pkgs map[string]*loaderPackage // keyed by Package.ID Config sizes types.Sizes // non-nil if needed by mode parseCache map[string]*parseValue @@ -738,9 +741,6 @@ func newLoader(cfg *Config) *loader { if ld.Config.Env == nil { ld.Config.Env = os.Environ() } - if ld.Config.gocmdRunner == nil { - ld.Config.gocmdRunner = &gocommand.Runner{} - } if ld.Context == nil { ld.Context = context.Background() } @@ -754,7 +754,7 @@ func newLoader(cfg *Config) *loader { ld.requestedMode = ld.Mode ld.Mode = impliedLoadMode(ld.Mode) - if ld.Mode&NeedTypes != 0 || ld.Mode&NeedSyntax != 0 { + if ld.Mode&(NeedSyntax|NeedTypes|NeedTypesInfo) != 0 { if ld.Fset == nil { ld.Fset = token.NewFileSet() } @@ -763,6 +763,7 @@ func newLoader(cfg *Config) *loader { // because we load source if export data is missing. if ld.ParseFile == nil { ld.ParseFile = func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) { + // We implicitly promise to keep doing ast.Object resolution. :( const mode = parser.AllErrors | parser.ParseComments return parser.ParseFile(fset, filename, src, mode) } @@ -794,7 +795,7 @@ func (ld *loader) refine(response *DriverResponse) ([]*Package, error) { exportDataInvalid := len(ld.Overlay) > 0 || pkg.ExportFile == "" && pkg.PkgPath != "unsafe" // This package needs type information if the caller requested types and the package is // either a root, or it's a non-root and the user requested dependencies ... - needtypes := (ld.Mode&NeedTypes|NeedTypesInfo != 0 && (rootIndex >= 0 || ld.Mode&NeedDeps != 0)) + needtypes := (ld.Mode&(NeedTypes|NeedTypesInfo) != 0 && (rootIndex >= 0 || ld.Mode&NeedDeps != 0)) // This package needs source if the call requested source (or types info, which implies source) // and the package is either a root, or itas a non- root and the user requested dependencies... needsrc := ((ld.Mode&(NeedSyntax|NeedTypesInfo) != 0 && (rootIndex >= 0 || ld.Mode&NeedDeps != 0)) || @@ -819,9 +820,10 @@ func (ld *loader) refine(response *DriverResponse) ([]*Package, error) { } } - if ld.Mode&NeedImports != 0 { - // Materialize the import graph. - + // Materialize the import graph if it is needed (NeedImports), + // or if we'll be using loadPackages (Need{Syntax|Types|TypesInfo}). + var leaves []*loaderPackage // packages with no unfinished successors + if ld.Mode&(NeedImports|NeedSyntax|NeedTypes|NeedTypesInfo) != 0 { const ( white = 0 // new grey = 1 // in progress @@ -840,63 +842,76 @@ func (ld *loader) refine(response *DriverResponse) ([]*Package, error) { // dependency on a package that does. These are the only packages // for which we load source code. var stack []*loaderPackage - var visit func(lpkg *loaderPackage) bool - visit = func(lpkg *loaderPackage) bool { - switch lpkg.color { - case black: - return lpkg.needsrc - case grey: + var visit func(from, lpkg *loaderPackage) bool + visit = func(from, lpkg *loaderPackage) bool { + if lpkg.color == grey { panic("internal error: grey node") } - lpkg.color = grey - stack = append(stack, lpkg) // push - stubs := lpkg.Imports // the structure form has only stubs with the ID in the Imports - lpkg.Imports = make(map[string]*Package, len(stubs)) - for importPath, ipkg := range stubs { - var importErr error - imp := ld.pkgs[ipkg.ID] - if imp == nil { - // (includes package "C" when DisableCgo) - importErr = fmt.Errorf("missing package: %q", ipkg.ID) - } else if imp.color == grey { - importErr = fmt.Errorf("import cycle: %s", stack) + if lpkg.color == white { + lpkg.color = grey + stack = append(stack, lpkg) // push + stubs := lpkg.Imports // the structure form has only stubs with the ID in the Imports + lpkg.Imports = make(map[string]*Package, len(stubs)) + for importPath, ipkg := range stubs { + var importErr error + imp := ld.pkgs[ipkg.ID] + if imp == nil { + // (includes package "C" when DisableCgo) + importErr = fmt.Errorf("missing package: %q", ipkg.ID) + } else if imp.color == grey { + importErr = fmt.Errorf("import cycle: %s", stack) + } + if importErr != nil { + if lpkg.importErrors == nil { + lpkg.importErrors = make(map[string]error) + } + lpkg.importErrors[importPath] = importErr + continue + } + + if visit(lpkg, imp) { + lpkg.needsrc = true + } + lpkg.Imports[importPath] = imp.Package } - if importErr != nil { - if lpkg.importErrors == nil { - lpkg.importErrors = make(map[string]error) + + // -- postorder -- + + // Complete type information is required for the + // immediate dependencies of each source package. + if lpkg.needsrc && ld.Mode&NeedTypes != 0 { + for _, ipkg := range lpkg.Imports { + ld.pkgs[ipkg.ID].needtypes = true } - lpkg.importErrors[importPath] = importErr - continue } - if visit(imp) { - lpkg.needsrc = true + // NeedTypeSizes causes TypeSizes to be set even + // on packages for which types aren't needed. + if ld.Mode&NeedTypesSizes != 0 { + lpkg.TypesSizes = ld.sizes } - lpkg.Imports[importPath] = imp.Package - } - // Complete type information is required for the - // immediate dependencies of each source package. - if lpkg.needsrc && ld.Mode&NeedTypes != 0 { - for _, ipkg := range lpkg.Imports { - ld.pkgs[ipkg.ID].needtypes = true + // Add packages with no imports directly to the queue of leaves. + if len(lpkg.Imports) == 0 { + leaves = append(leaves, lpkg) } + + stack = stack[:len(stack)-1] // pop + lpkg.color = black } - // NeedTypeSizes causes TypeSizes to be set even - // on packages for which types aren't needed. - if ld.Mode&NeedTypesSizes != 0 { - lpkg.TypesSizes = ld.sizes + // Add edge from predecessor. + if from != nil { + from.unfinishedSuccs.Add(+1) // incref + lpkg.preds = append(lpkg.preds, from) } - stack = stack[:len(stack)-1] // pop - lpkg.color = black return lpkg.needsrc } // For each initial package, create its import DAG. for _, lpkg := range initial { - visit(lpkg) + visit(nil, lpkg) } } else { @@ -909,16 +924,45 @@ func (ld *loader) refine(response *DriverResponse) ([]*Package, error) { // Load type data and syntax if needed, starting at // the initial packages (roots of the import DAG). - if ld.Mode&NeedTypes != 0 || ld.Mode&NeedSyntax != 0 { - var wg sync.WaitGroup - for _, lpkg := range initial { - wg.Add(1) - go func(lpkg *loaderPackage) { - ld.loadRecursive(lpkg) - wg.Done() - }(lpkg) + if ld.Mode&(NeedSyntax|NeedTypes|NeedTypesInfo) != 0 { + + // We avoid using g.SetLimit to limit concurrency as + // it makes g.Go stop accepting work, which prevents + // workers from enqeuing, and thus finishing, and thus + // allowing the group to make progress: deadlock. + // + // Instead we use the ioLimit and cpuLimit semaphores. + g, _ := errgroup.WithContext(ld.Context) + + // enqueues adds a package to the type-checking queue. + // It must have no unfinished successors. + var enqueue func(*loaderPackage) + enqueue = func(lpkg *loaderPackage) { + g.Go(func() error { + // Parse and type-check. + ld.loadPackage(lpkg) + + // Notify each waiting predecessor, + // and enqueue it when it becomes a leaf. + for _, pred := range lpkg.preds { + if pred.unfinishedSuccs.Add(-1) == 0 { // decref + enqueue(pred) + } + } + + return nil + }) + } + + // Load leaves first, adding new packages + // to the queue as they become leaves. + for _, leaf := range leaves { + enqueue(leaf) + } + + if err := g.Wait(); err != nil { + return nil, err // cancelled } - wg.Wait() } // If the context is done, return its error and @@ -965,7 +1009,7 @@ func (ld *loader) refine(response *DriverResponse) ([]*Package, error) { if ld.requestedMode&NeedSyntax == 0 { ld.pkgs[i].Syntax = nil } - if ld.requestedMode&NeedTypes == 0 && ld.requestedMode&NeedSyntax == 0 { + if ld.requestedMode&(NeedSyntax|NeedTypes|NeedTypesInfo) == 0 { ld.pkgs[i].Fset = nil } if ld.requestedMode&NeedTypesInfo == 0 { @@ -982,31 +1026,10 @@ func (ld *loader) refine(response *DriverResponse) ([]*Package, error) { return result, nil } -// loadRecursive loads the specified package and its dependencies, -// recursively, in parallel, in topological order. -// It is atomic and idempotent. -// Precondition: ld.Mode&NeedTypes. -func (ld *loader) loadRecursive(lpkg *loaderPackage) { - lpkg.loadOnce.Do(func() { - // Load the direct dependencies, in parallel. - var wg sync.WaitGroup - for _, ipkg := range lpkg.Imports { - imp := ld.pkgs[ipkg.ID] - wg.Add(1) - go func(imp *loaderPackage) { - ld.loadRecursive(imp) - wg.Done() - }(imp) - } - wg.Wait() - ld.loadPackage(lpkg) - }) -} - -// loadPackage loads the specified package. +// loadPackage loads/parses/typechecks the specified package. // It must be called only once per Package, // after immediate dependencies are loaded. -// Precondition: ld.Mode & NeedTypes. +// Precondition: ld.Mode&(NeedSyntax|NeedTypes|NeedTypesInfo) != 0. func (ld *loader) loadPackage(lpkg *loaderPackage) { if lpkg.PkgPath == "unsafe" { // Fill in the blanks to avoid surprises. @@ -1042,6 +1065,10 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) { if !lpkg.needtypes && !lpkg.needsrc { return } + + // TODO(adonovan): this condition looks wrong: + // I think it should be lpkg.needtypes && !lpg.needsrc, + // so that NeedSyntax without NeedTypes can be satisfied by export data. if !lpkg.needsrc { if err := ld.loadFromExportData(lpkg); err != nil { lpkg.Errors = append(lpkg.Errors, Error{ @@ -1147,7 +1174,7 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) { } lpkg.Syntax = files - if ld.Config.Mode&NeedTypes == 0 { + if ld.Config.Mode&(NeedTypes|NeedTypesInfo) == 0 { return } @@ -1158,16 +1185,20 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) { return } - lpkg.TypesInfo = &types.Info{ - Types: make(map[ast.Expr]types.TypeAndValue), - Defs: make(map[*ast.Ident]types.Object), - Uses: make(map[*ast.Ident]types.Object), - Implicits: make(map[ast.Node]types.Object), - Instances: make(map[*ast.Ident]types.Instance), - Scopes: make(map[ast.Node]*types.Scope), - Selections: make(map[*ast.SelectorExpr]*types.Selection), + // Populate TypesInfo only if needed, as it + // causes the type checker to work much harder. + if ld.Config.Mode&NeedTypesInfo != 0 { + lpkg.TypesInfo = &types.Info{ + Types: make(map[ast.Expr]types.TypeAndValue), + Defs: make(map[*ast.Ident]types.Object), + Uses: make(map[*ast.Ident]types.Object), + Implicits: make(map[ast.Node]types.Object), + Instances: make(map[*ast.Ident]types.Instance), + Scopes: make(map[ast.Node]*types.Scope), + Selections: make(map[*ast.SelectorExpr]*types.Selection), + FileVersions: make(map[*ast.File]string), + } } - versions.InitFileVersions(lpkg.TypesInfo) lpkg.TypesSizes = ld.sizes importer := importerFunc(func(path string) (*types.Package, error) { @@ -1220,6 +1251,10 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) { } } + // Type-checking is CPU intensive. + cpuLimit <- unit{} // acquire a token + defer func() { <-cpuLimit }() // release a token + typErr := types.NewChecker(tc, ld.Fset, lpkg.Types, lpkg.TypesInfo).Files(lpkg.Syntax) lpkg.importErrors = nil // no longer needed @@ -1284,8 +1319,11 @@ type importerFunc func(path string) (*types.Package, error) func (f importerFunc) Import(path string) (*types.Package, error) { return f(path) } // We use a counting semaphore to limit -// the number of parallel I/O calls per process. -var ioLimit = make(chan bool, 20) +// the number of parallel I/O calls or CPU threads per process. +var ( + ioLimit = make(chan unit, 20) + cpuLimit = make(chan unit, runtime.GOMAXPROCS(0)) +) func (ld *loader) parseFile(filename string) (*ast.File, error) { ld.parseCacheMu.Lock() @@ -1302,20 +1340,28 @@ func (ld *loader) parseFile(filename string) (*ast.File, error) { var src []byte for f, contents := range ld.Config.Overlay { + // TODO(adonovan): Inefficient for large overlays. + // Do an exact name-based map lookup + // (for nonexistent files) followed by a + // FileID-based map lookup (for existing ones). if sameFile(f, filename) { src = contents + break } } var err error if src == nil { - ioLimit <- true // wait + ioLimit <- unit{} // acquire a token src, err = os.ReadFile(filename) - <-ioLimit // signal + <-ioLimit // release a token } if err != nil { v.err = err } else { + // Parsing is CPU intensive. + cpuLimit <- unit{} // acquire a token v.f, v.err = ld.ParseFile(ld.Fset, filename, src) + <-cpuLimit // release a token } close(v.ready) @@ -1330,18 +1376,21 @@ func (ld *loader) parseFile(filename string) (*ast.File, error) { // Because files are scanned in parallel, the token.Pos // positions of the resulting ast.Files are not ordered. func (ld *loader) parseFiles(filenames []string) ([]*ast.File, []error) { - var wg sync.WaitGroup - n := len(filenames) - parsed := make([]*ast.File, n) - errors := make([]error, n) - for i, file := range filenames { - wg.Add(1) - go func(i int, filename string) { + var ( + n = len(filenames) + parsed = make([]*ast.File, n) + errors = make([]error, n) + ) + var g errgroup.Group + for i, filename := range filenames { + // This creates goroutines unnecessarily in the + // cache-hit case, but that case is uncommon. + g.Go(func() error { parsed[i], errors[i] = ld.parseFile(filename) - wg.Done() - }(i, file) + return nil + }) } - wg.Wait() + g.Wait() // Eliminate nils, preserving order. var o int @@ -1512,4 +1561,4 @@ func usesExportData(cfg *Config) bool { return cfg.Mode&NeedExportFile != 0 || cfg.Mode&NeedTypes != 0 && cfg.Mode&NeedDeps == 0 } -var _ interface{} = io.Discard // assert build toolchain is go1.16 or later +type unit struct{} 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 9ada177758..16ed3c1780 100644 --- a/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go +++ b/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go @@ -228,7 +228,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) { // Reject obviously non-viable cases. switch obj := obj.(type) { case *types.TypeName: - if _, ok := aliases.Unalias(obj.Type()).(*types.TypeParam); !ok { + if _, ok := types.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) @@ -280,26 +280,26 @@ func (enc *Encoder) For(obj types.Object) (Path, error) { path = append(path, opType) T := o.Type() - if alias, ok := T.(*aliases.Alias); ok { - if r := findTypeParam(obj, aliases.TypeParams(alias), path, opTypeParam, nil); r != nil { + if alias, ok := T.(*types.Alias); ok { + if r := findTypeParam(obj, aliases.TypeParams(alias), path, opTypeParam); r != nil { return Path(r), nil } - if r := find(obj, aliases.Rhs(alias), append(path, opRhs), nil); r != nil { + if r := find(obj, aliases.Rhs(alias), append(path, opRhs)); r != nil { return Path(r), nil } } else if tname.IsAlias() { // legacy alias - if r := find(obj, T, path, nil); r != nil { + if r := find(obj, T, path); r != nil { return Path(r), nil } } else if named, ok := T.(*types.Named); ok { // defined (named) type - if r := findTypeParam(obj, named.TypeParams(), path, opTypeParam, nil); r != nil { + if r := findTypeParam(obj, named.TypeParams(), path, opTypeParam); r != nil { return Path(r), nil } - if r := find(obj, named.Underlying(), append(path, opUnderlying), nil); r != nil { + if r := find(obj, named.Underlying(), append(path, opUnderlying)); r != nil { return Path(r), nil } } @@ -312,7 +312,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) { if _, ok := o.(*types.TypeName); !ok { if o.Exported() { // exported non-type (const, var, func) - if r := find(obj, o.Type(), append(path, opType), nil); r != nil { + if r := find(obj, o.Type(), append(path, opType)); r != nil { return Path(r), nil } } @@ -320,7 +320,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) { } // Inspect declared methods of defined types. - if T, ok := aliases.Unalias(o.Type()).(*types.Named); ok { + if T, ok := types.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, @@ -332,7 +332,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) { if m == obj { return Path(path2), nil // found declared method } - if r := find(obj, m.Type(), append(path2, opType), nil); r != nil { + if r := find(obj, m.Type(), append(path2, opType)); r != nil { return Path(r), nil } } @@ -447,46 +447,64 @@ func (enc *Encoder) concreteMethod(meth *types.Func) (Path, bool) { // // The seen map is used to short circuit cycles through type parameters. If // nil, it will be allocated as necessary. -func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName]bool) []byte { +// +// The seenMethods map is used internally to short circuit cycles through +// interface methods, such as occur in the following example: +// +// type I interface { f() interface{I} } +// +// See golang/go#68046 for details. +func find(obj types.Object, T types.Type, path []byte) []byte { + return (&finder{obj: obj}).find(T, path) +} + +// finder closes over search state for a call to find. +type finder struct { + obj types.Object // the sought object + seenTParamNames map[*types.TypeName]bool // for cycle breaking through type parameters + seenMethods map[*types.Func]bool // for cycle breaking through recursive interfaces +} + +func (f *finder) find(T types.Type, path []byte) []byte { switch T := T.(type) { - case *aliases.Alias: - return find(obj, aliases.Unalias(T), path, seen) + case *types.Alias: + return f.find(types.Unalias(T), path) case *types.Basic, *types.Named: // Named types belonging to pkg were handled already, // so T must belong to another package. No path. return nil case *types.Pointer: - return find(obj, T.Elem(), append(path, opElem), seen) + return f.find(T.Elem(), append(path, opElem)) case *types.Slice: - return find(obj, T.Elem(), append(path, opElem), seen) + return f.find(T.Elem(), append(path, opElem)) case *types.Array: - return find(obj, T.Elem(), append(path, opElem), seen) + return f.find(T.Elem(), append(path, opElem)) case *types.Chan: - return find(obj, T.Elem(), append(path, opElem), seen) + return f.find(T.Elem(), append(path, opElem)) case *types.Map: - if r := find(obj, T.Key(), append(path, opKey), seen); r != nil { + if r := f.find(T.Key(), append(path, opKey)); r != nil { return r } - return find(obj, T.Elem(), append(path, opElem), seen) + return f.find(T.Elem(), append(path, opElem)) case *types.Signature: - if r := findTypeParam(obj, T.RecvTypeParams(), path, opRecvTypeParam, nil); r != nil { + if r := f.findTypeParam(T.RecvTypeParams(), path, opRecvTypeParam); r != nil { return r } - if r := findTypeParam(obj, T.TypeParams(), path, opTypeParam, seen); r != nil { + if r := f.findTypeParam(T.TypeParams(), path, opTypeParam); r != nil { return r } - if r := find(obj, T.Params(), append(path, opParams), seen); r != nil { + if r := f.find(T.Params(), append(path, opParams)); r != nil { return r } - return find(obj, T.Results(), append(path, opResults), seen) + return f.find(T.Results(), append(path, opResults)) case *types.Struct: for i := 0; i < T.NumFields(); i++ { fld := T.Field(i) path2 := appendOpArg(path, opField, i) - if fld == obj { + if fld == f.obj { return path2 // found field var } - if r := find(obj, fld.Type(), append(path2, opType), seen); r != nil { + if r := f.find(fld.Type(), append(path2, opType)); r != nil { return r } } @@ -495,10 +513,10 @@ func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName] for i := 0; i < T.Len(); i++ { v := T.At(i) path2 := appendOpArg(path, opAt, i) - if v == obj { + if v == f.obj { return path2 // found param/result var } - if r := find(obj, v.Type(), append(path2, opType), seen); r != nil { + if r := f.find(v.Type(), append(path2, opType)); r != nil { return r } } @@ -506,28 +524,35 @@ func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName] case *types.Interface: for i := 0; i < T.NumMethods(); i++ { m := T.Method(i) + if f.seenMethods[m] { + return nil + } path2 := appendOpArg(path, opMethod, i) - if m == obj { + if m == f.obj { return path2 // found interface method } - if r := find(obj, m.Type(), append(path2, opType), seen); r != nil { + if f.seenMethods == nil { + f.seenMethods = make(map[*types.Func]bool) + } + f.seenMethods[m] = true + if r := f.find(m.Type(), append(path2, opType)); r != nil { return r } } return nil case *types.TypeParam: name := T.Obj() - if name == obj { - return append(path, opObj) - } - if seen[name] { + if f.seenTParamNames[name] { return nil } - if seen == nil { - seen = make(map[*types.TypeName]bool) + if name == f.obj { + return append(path, opObj) } - seen[name] = true - if r := find(obj, T.Constraint(), append(path, opConstraint), seen); r != nil { + if f.seenTParamNames == nil { + f.seenTParamNames = make(map[*types.TypeName]bool) + } + f.seenTParamNames[name] = true + if r := f.find(T.Constraint(), append(path, opConstraint)); r != nil { return r } return nil @@ -535,11 +560,15 @@ func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName] panic(T) } -func findTypeParam(obj types.Object, list *types.TypeParamList, path []byte, op byte, seen map[*types.TypeName]bool) []byte { +func findTypeParam(obj types.Object, list *types.TypeParamList, path []byte, op byte) []byte { + return (&finder{obj: obj}).findTypeParam(list, path, op) +} + +func (f *finder) findTypeParam(list *types.TypeParamList, path []byte, op byte) []byte { for i := 0; i < list.Len(); i++ { tparam := list.At(i) path2 := appendOpArg(path, op, i) - if r := find(obj, tparam, path2, seen); r != nil { + if r := f.find(tparam, path2); r != nil { return r } } @@ -626,7 +655,7 @@ func Object(pkg *types.Package, p Path) (types.Object, error) { // Inv: t != nil, obj == nil - t = aliases.Unalias(t) + t = types.Unalias(t) switch code { case opElem: hasElem, ok := t.(hasElem) // Pointer, Slice, Array, Chan, Map @@ -664,7 +693,7 @@ func Object(pkg *types.Package, p Path) (types.Object, error) { t = named.Underlying() case opRhs: - if alias, ok := t.(*aliases.Alias); ok { + if alias, ok := t.(*types.Alias); ok { t = aliases.Rhs(alias) } else if false && aliases.Enabled() { // The Enabled check is too expensive, so for now we diff --git a/vendor/golang.org/x/tools/go/types/typeutil/callee.go b/vendor/golang.org/x/tools/go/types/typeutil/callee.go new file mode 100644 index 0000000000..754380351e --- /dev/null +++ b/vendor/golang.org/x/tools/go/types/typeutil/callee.go @@ -0,0 +1,68 @@ +// 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. + +package typeutil + +import ( + "go/ast" + "go/types" + + "golang.org/x/tools/internal/typeparams" +) + +// Callee returns the named target of a function call, if any: +// a function, method, builtin, or variable. +// +// Functions and methods may potentially have type parameters. +func Callee(info *types.Info, call *ast.CallExpr) types.Object { + fun := ast.Unparen(call.Fun) + + // Look through type instantiation if necessary. + isInstance := false + switch fun.(type) { + case *ast.IndexExpr, *ast.IndexListExpr: + // When extracting the callee from an *IndexExpr, we need to check that + // it is a *types.Func and not a *types.Var. + // Example: Don't match a slice m within the expression `m[0]()`. + isInstance = true + fun, _, _, _ = typeparams.UnpackIndexExpr(fun) + } + + var obj types.Object + switch fun := fun.(type) { + case *ast.Ident: + obj = info.Uses[fun] // type, var, builtin, or declared func + case *ast.SelectorExpr: + if sel, ok := info.Selections[fun]; ok { + obj = sel.Obj() // method or field + } else { + obj = info.Uses[fun.Sel] // qualified identifier? + } + } + if _, ok := obj.(*types.TypeName); ok { + return nil // T(x) is a conversion, not a call + } + // A Func is required to match instantiations. + if _, ok := obj.(*types.Func); isInstance && !ok { + return nil // Was not a Func. + } + return obj +} + +// StaticCallee returns the target (function or method) of a static function +// call, if any. It returns nil for calls to builtins. +// +// Note: for calls of instantiated functions and methods, StaticCallee returns +// the corresponding generic function or method on the generic type. +func StaticCallee(info *types.Info, call *ast.CallExpr) *types.Func { + if f, ok := Callee(info, call).(*types.Func); ok && !interfaceMethod(f) { + return f + } + return nil +} + +func interfaceMethod(f *types.Func) bool { + recv := f.Type().(*types.Signature).Recv() + return recv != nil && types.IsInterface(recv.Type()) +} diff --git a/vendor/golang.org/x/tools/go/types/typeutil/imports.go b/vendor/golang.org/x/tools/go/types/typeutil/imports.go new file mode 100644 index 0000000000..b81ce0c330 --- /dev/null +++ b/vendor/golang.org/x/tools/go/types/typeutil/imports.go @@ -0,0 +1,30 @@ +// Copyright 2014 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 typeutil + +import "go/types" + +// Dependencies returns all dependencies of the specified packages. +// +// Dependent packages appear in topological order: if package P imports +// package Q, Q appears earlier than P in the result. +// The algorithm follows import statements in the order they +// appear in the source code, so the result is a total order. +func Dependencies(pkgs ...*types.Package) []*types.Package { + var result []*types.Package + seen := make(map[*types.Package]bool) + var visit func(pkgs []*types.Package) + visit = func(pkgs []*types.Package) { + for _, p := range pkgs { + if !seen[p] { + seen[p] = true + visit(p.Imports()) + result = append(result, p) + } + } + } + visit(pkgs) + return result +} diff --git a/vendor/golang.org/x/tools/go/types/typeutil/map.go b/vendor/golang.org/x/tools/go/types/typeutil/map.go new file mode 100644 index 0000000000..8d824f7140 --- /dev/null +++ b/vendor/golang.org/x/tools/go/types/typeutil/map.go @@ -0,0 +1,517 @@ +// Copyright 2014 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 typeutil defines various utilities for types, such as Map, +// a mapping from types.Type to any values. +package typeutil // import "golang.org/x/tools/go/types/typeutil" + +import ( + "bytes" + "fmt" + "go/types" + "reflect" + + "golang.org/x/tools/internal/typeparams" +) + +// Map is a hash-table-based mapping from types (types.Type) to +// arbitrary any values. The concrete types that implement +// the Type interface are pointers. Since they are not canonicalized, +// == cannot be used to check for equivalence, and thus we cannot +// simply use a Go map. +// +// Just as with map[K]V, a nil *Map is a valid empty map. +// +// Not thread-safe. +type Map struct { + hasher Hasher // shared by many Maps + table map[uint32][]entry // maps hash to bucket; entry.key==nil means unused + length int // number of map entries +} + +// entry is an entry (key/value association) in a hash bucket. +type entry struct { + key types.Type + value any +} + +// SetHasher sets the hasher used by Map. +// +// All Hashers are functionally equivalent but contain internal state +// used to cache the results of hashing previously seen types. +// +// A single Hasher created by MakeHasher() may be shared among many +// Maps. This is recommended if the instances have many keys in +// common, as it will amortize the cost of hash computation. +// +// A Hasher may grow without bound as new types are seen. Even when a +// type is deleted from the map, the Hasher never shrinks, since other +// types in the map may reference the deleted type indirectly. +// +// Hashers are not thread-safe, and read-only operations such as +// Map.Lookup require updates to the hasher, so a full Mutex lock (not a +// read-lock) is require around all Map operations if a shared +// hasher is accessed from multiple threads. +// +// If SetHasher is not called, the Map will create a private hasher at +// the first call to Insert. +func (m *Map) SetHasher(hasher Hasher) { + m.hasher = hasher +} + +// Delete removes the entry with the given key, if any. +// It returns true if the entry was found. +func (m *Map) Delete(key types.Type) bool { + if m != nil && m.table != nil { + hash := m.hasher.Hash(key) + bucket := m.table[hash] + for i, e := range bucket { + if e.key != nil && types.Identical(key, e.key) { + // We can't compact the bucket as it + // would disturb iterators. + bucket[i] = entry{} + m.length-- + return true + } + } + } + return false +} + +// At returns the map entry for the given key. +// The result is nil if the entry is not present. +func (m *Map) At(key types.Type) any { + if m != nil && m.table != nil { + for _, e := range m.table[m.hasher.Hash(key)] { + if e.key != nil && types.Identical(key, e.key) { + return e.value + } + } + } + return nil +} + +// Set sets the map entry for key to val, +// and returns the previous entry, if any. +func (m *Map) Set(key types.Type, value any) (prev any) { + if m.table != nil { + hash := m.hasher.Hash(key) + bucket := m.table[hash] + var hole *entry + for i, e := range bucket { + if e.key == nil { + hole = &bucket[i] + } else if types.Identical(key, e.key) { + prev = e.value + bucket[i].value = value + return + } + } + + if hole != nil { + *hole = entry{key, value} // overwrite deleted entry + } else { + m.table[hash] = append(bucket, entry{key, value}) + } + } else { + if m.hasher.memo == nil { + m.hasher = MakeHasher() + } + hash := m.hasher.Hash(key) + m.table = map[uint32][]entry{hash: {entry{key, value}}} + } + + m.length++ + return +} + +// Len returns the number of map entries. +func (m *Map) Len() int { + if m != nil { + return m.length + } + return 0 +} + +// Iterate calls function f on each entry in the map in unspecified order. +// +// If f should mutate the map, Iterate provides the same guarantees as +// Go maps: if f deletes a map entry that Iterate has not yet reached, +// f will not be invoked for it, but if f inserts a map entry that +// Iterate has not yet reached, whether or not f will be invoked for +// it is unspecified. +func (m *Map) Iterate(f func(key types.Type, value any)) { + if m != nil { + for _, bucket := range m.table { + for _, e := range bucket { + if e.key != nil { + f(e.key, e.value) + } + } + } + } +} + +// Keys returns a new slice containing the set of map keys. +// The order is unspecified. +func (m *Map) Keys() []types.Type { + keys := make([]types.Type, 0, m.Len()) + m.Iterate(func(key types.Type, _ any) { + keys = append(keys, key) + }) + return keys +} + +func (m *Map) toString(values bool) string { + if m == nil { + return "{}" + } + var buf bytes.Buffer + fmt.Fprint(&buf, "{") + sep := "" + m.Iterate(func(key types.Type, value any) { + fmt.Fprint(&buf, sep) + sep = ", " + fmt.Fprint(&buf, key) + if values { + fmt.Fprintf(&buf, ": %q", value) + } + }) + fmt.Fprint(&buf, "}") + return buf.String() +} + +// String returns a string representation of the map's entries. +// Values are printed using fmt.Sprintf("%v", v). +// Order is unspecified. +func (m *Map) String() string { + return m.toString(true) +} + +// KeysString returns a string representation of the map's key set. +// Order is unspecified. +func (m *Map) KeysString() string { + return m.toString(false) +} + +//////////////////////////////////////////////////////////////////////// +// Hasher + +// A Hasher maps each type to its hash value. +// For efficiency, a hasher uses memoization; thus its memory +// footprint grows monotonically over time. +// Hashers are not thread-safe. +// Hashers have reference semantics. +// Call MakeHasher to create a Hasher. +type Hasher struct { + memo map[types.Type]uint32 + + // ptrMap records pointer identity. + ptrMap map[any]uint32 + + // sigTParams holds type parameters from the signature being hashed. + // Signatures are considered identical modulo renaming of type parameters, so + // within the scope of a signature type the identity of the signature's type + // parameters is just their index. + // + // Since the language does not currently support referring to uninstantiated + // generic types or functions, and instantiated signatures do not have type + // parameter lists, we should never encounter a second non-empty type + // parameter list when hashing a generic signature. + sigTParams *types.TypeParamList +} + +// MakeHasher returns a new Hasher instance. +func MakeHasher() Hasher { + return Hasher{ + memo: make(map[types.Type]uint32), + ptrMap: make(map[any]uint32), + sigTParams: nil, + } +} + +// Hash computes a hash value for the given type t such that +// Identical(t, t') => Hash(t) == Hash(t'). +func (h Hasher) Hash(t types.Type) uint32 { + hash, ok := h.memo[t] + if !ok { + hash = h.hashFor(t) + h.memo[t] = hash + } + return hash +} + +// hashString computes the Fowler–Noll–Vo hash of s. +func hashString(s string) uint32 { + var h uint32 + for i := 0; i < len(s); i++ { + h ^= uint32(s[i]) + h *= 16777619 + } + return h +} + +// hashFor computes the hash of t. +func (h Hasher) hashFor(t types.Type) uint32 { + // See Identical for rationale. + switch t := t.(type) { + case *types.Basic: + return uint32(t.Kind()) + + case *types.Alias: + return h.Hash(types.Unalias(t)) + + case *types.Array: + return 9043 + 2*uint32(t.Len()) + 3*h.Hash(t.Elem()) + + case *types.Slice: + return 9049 + 2*h.Hash(t.Elem()) + + case *types.Struct: + var hash uint32 = 9059 + for i, n := 0, t.NumFields(); i < n; i++ { + f := t.Field(i) + if f.Anonymous() { + hash += 8861 + } + hash += hashString(t.Tag(i)) + hash += hashString(f.Name()) // (ignore f.Pkg) + hash += h.Hash(f.Type()) + } + return hash + + case *types.Pointer: + return 9067 + 2*h.Hash(t.Elem()) + + case *types.Signature: + var hash uint32 = 9091 + if t.Variadic() { + hash *= 8863 + } + + // Use a separate hasher for types inside of the signature, where type + // parameter identity is modified to be (index, constraint). We must use a + // new memo for this hasher as type identity may be affected by this + // masking. For example, in func[T any](*T), the identity of *T depends on + // whether we are mapping the argument in isolation, or recursively as part + // of hashing the signature. + // + // We should never encounter a generic signature while hashing another + // generic signature, but defensively set sigTParams only if h.mask is + // unset. + tparams := t.TypeParams() + if h.sigTParams == nil && tparams.Len() != 0 { + h = Hasher{ + // There may be something more efficient than discarding the existing + // memo, but it would require detecting whether types are 'tainted' by + // references to type parameters. + memo: make(map[types.Type]uint32), + // Re-using ptrMap ensures that pointer identity is preserved in this + // hasher. + ptrMap: h.ptrMap, + sigTParams: tparams, + } + } + + for i := 0; i < tparams.Len(); i++ { + tparam := tparams.At(i) + hash += 7 * h.Hash(tparam.Constraint()) + } + + return hash + 3*h.hashTuple(t.Params()) + 5*h.hashTuple(t.Results()) + + case *types.Union: + return h.hashUnion(t) + + case *types.Interface: + // Interfaces are identical if they have the same set of methods, with + // identical names and types, and they have the same set of type + // restrictions. See go/types.identical for more details. + var hash uint32 = 9103 + + // Hash methods. + for i, n := 0, t.NumMethods(); i < n; i++ { + // Method order is not significant. + // Ignore m.Pkg(). + m := t.Method(i) + // Use shallow hash on method signature to + // avoid anonymous interface cycles. + hash += 3*hashString(m.Name()) + 5*h.shallowHash(m.Type()) + } + + // Hash type restrictions. + terms, err := typeparams.InterfaceTermSet(t) + // if err != nil t has invalid type restrictions. + if err == nil { + hash += h.hashTermSet(terms) + } + + return hash + + case *types.Map: + return 9109 + 2*h.Hash(t.Key()) + 3*h.Hash(t.Elem()) + + case *types.Chan: + return 9127 + 2*uint32(t.Dir()) + 3*h.Hash(t.Elem()) + + case *types.Named: + hash := h.hashPtr(t.Obj()) + targs := t.TypeArgs() + for i := 0; i < targs.Len(); i++ { + targ := targs.At(i) + hash += 2 * h.Hash(targ) + } + return hash + + case *types.TypeParam: + return h.hashTypeParam(t) + + case *types.Tuple: + return h.hashTuple(t) + } + + panic(fmt.Sprintf("%T: %v", t, t)) +} + +func (h Hasher) hashTuple(tuple *types.Tuple) uint32 { + // See go/types.identicalTypes for rationale. + n := tuple.Len() + hash := 9137 + 2*uint32(n) + for i := 0; i < n; i++ { + hash += 3 * h.Hash(tuple.At(i).Type()) + } + return hash +} + +func (h Hasher) hashUnion(t *types.Union) uint32 { + // Hash type restrictions. + terms, err := typeparams.UnionTermSet(t) + // if err != nil t has invalid type restrictions. Fall back on a non-zero + // hash. + if err != nil { + return 9151 + } + return h.hashTermSet(terms) +} + +func (h Hasher) hashTermSet(terms []*types.Term) uint32 { + hash := 9157 + 2*uint32(len(terms)) + for _, term := range terms { + // term order is not significant. + termHash := h.Hash(term.Type()) + if term.Tilde() { + termHash *= 9161 + } + hash += 3 * termHash + } + return hash +} + +// hashTypeParam returns a hash of the type parameter t, with a hash value +// depending on whether t is contained in h.sigTParams. +// +// If h.sigTParams is set and contains t, then we are in the process of hashing +// a signature, and the hash value of t must depend only on t's index and +// constraint: signatures are considered identical modulo type parameter +// renaming. To avoid infinite recursion, we only hash the type parameter +// index, and rely on types.Identical to handle signatures where constraints +// are not identical. +// +// Otherwise the hash of t depends only on t's pointer identity. +func (h Hasher) hashTypeParam(t *types.TypeParam) uint32 { + if h.sigTParams != nil { + i := t.Index() + if i >= 0 && i < h.sigTParams.Len() && t == h.sigTParams.At(i) { + return 9173 + 3*uint32(i) + } + } + return h.hashPtr(t.Obj()) +} + +// hashPtr hashes the pointer identity of ptr. It uses h.ptrMap to ensure that +// pointers values are not dependent on the GC. +func (h Hasher) hashPtr(ptr any) uint32 { + if hash, ok := h.ptrMap[ptr]; ok { + return hash + } + hash := uint32(reflect.ValueOf(ptr).Pointer()) + h.ptrMap[ptr] = hash + return hash +} + +// shallowHash computes a hash of t without looking at any of its +// element Types, to avoid potential anonymous cycles in the types of +// interface methods. +// +// When an unnamed non-empty interface type appears anywhere among the +// arguments or results of an interface method, there is a potential +// for endless recursion. Consider: +// +// type X interface { m() []*interface { X } } +// +// The problem is that the Methods of the interface in m's result type +// include m itself; there is no mention of the named type X that +// might help us break the cycle. +// (See comment in go/types.identical, case *Interface, for more.) +func (h Hasher) shallowHash(t types.Type) uint32 { + // t is the type of an interface method (Signature), + // its params or results (Tuples), or their immediate + // elements (mostly Slice, Pointer, Basic, Named), + // so there's no need to optimize anything else. + switch t := t.(type) { + case *types.Alias: + return h.shallowHash(types.Unalias(t)) + + case *types.Signature: + var hash uint32 = 604171 + if t.Variadic() { + hash *= 971767 + } + // The Signature/Tuple recursion is always finite + // and invariably shallow. + return hash + 1062599*h.shallowHash(t.Params()) + 1282529*h.shallowHash(t.Results()) + + case *types.Tuple: + n := t.Len() + hash := 9137 + 2*uint32(n) + for i := 0; i < n; i++ { + hash += 53471161 * h.shallowHash(t.At(i).Type()) + } + return hash + + case *types.Basic: + return 45212177 * uint32(t.Kind()) + + case *types.Array: + return 1524181 + 2*uint32(t.Len()) + + case *types.Slice: + return 2690201 + + case *types.Struct: + return 3326489 + + case *types.Pointer: + return 4393139 + + case *types.Union: + return 562448657 + + case *types.Interface: + return 2124679 // no recursion here + + case *types.Map: + return 9109 + + case *types.Chan: + return 9127 + + case *types.Named: + return h.hashPtr(t.Obj()) + + case *types.TypeParam: + return h.hashPtr(t.Obj()) + } + panic(fmt.Sprintf("shallowHash: %T: %v", t, t)) +} diff --git a/vendor/golang.org/x/tools/go/types/typeutil/methodsetcache.go b/vendor/golang.org/x/tools/go/types/typeutil/methodsetcache.go new file mode 100644 index 0000000000..f7666028fe --- /dev/null +++ b/vendor/golang.org/x/tools/go/types/typeutil/methodsetcache.go @@ -0,0 +1,71 @@ +// Copyright 2014 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 implements a cache of method sets. + +package typeutil + +import ( + "go/types" + "sync" +) + +// A MethodSetCache records the method set of each type T for which +// MethodSet(T) is called so that repeat queries are fast. +// The zero value is a ready-to-use cache instance. +type MethodSetCache struct { + mu sync.Mutex + named map[*types.Named]struct{ value, pointer *types.MethodSet } // method sets for named N and *N + others map[types.Type]*types.MethodSet // all other types +} + +// MethodSet returns the method set of type T. It is thread-safe. +// +// If cache is nil, this function is equivalent to types.NewMethodSet(T). +// Utility functions can thus expose an optional *MethodSetCache +// parameter to clients that care about performance. +func (cache *MethodSetCache) MethodSet(T types.Type) *types.MethodSet { + if cache == nil { + return types.NewMethodSet(T) + } + cache.mu.Lock() + defer cache.mu.Unlock() + + switch T := types.Unalias(T).(type) { + case *types.Named: + return cache.lookupNamed(T).value + + case *types.Pointer: + if N, ok := types.Unalias(T.Elem()).(*types.Named); ok { + return cache.lookupNamed(N).pointer + } + } + + // all other types + // (The map uses pointer equivalence, not type identity.) + mset := cache.others[T] + if mset == nil { + mset = types.NewMethodSet(T) + if cache.others == nil { + cache.others = make(map[types.Type]*types.MethodSet) + } + cache.others[T] = mset + } + return mset +} + +func (cache *MethodSetCache) lookupNamed(named *types.Named) struct{ value, pointer *types.MethodSet } { + if cache.named == nil { + cache.named = make(map[*types.Named]struct{ value, pointer *types.MethodSet }) + } + // Avoid recomputing mset(*T) for each distinct Pointer + // instance whose underlying type is a named type. + msets, ok := cache.named[named] + if !ok { + msets.value = types.NewMethodSet(named) + msets.pointer = types.NewMethodSet(types.NewPointer(named)) + cache.named[named] = msets + } + return msets +} diff --git a/vendor/golang.org/x/tools/go/types/typeutil/ui.go b/vendor/golang.org/x/tools/go/types/typeutil/ui.go new file mode 100644 index 0000000000..9dda6a25df --- /dev/null +++ b/vendor/golang.org/x/tools/go/types/typeutil/ui.go @@ -0,0 +1,53 @@ +// Copyright 2014 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 typeutil + +// This file defines utilities for user interfaces that display types. + +import ( + "go/types" +) + +// IntuitiveMethodSet returns the intuitive method set of a type T, +// which is the set of methods you can call on an addressable value of +// that type. +// +// The result always contains MethodSet(T), and is exactly MethodSet(T) +// for interface types and for pointer-to-concrete types. +// For all other concrete types T, the result additionally +// contains each method belonging to *T if there is no identically +// named method on T itself. +// +// This corresponds to user intuition about method sets; +// this function is intended only for user interfaces. +// +// The order of the result is as for types.MethodSet(T). +func IntuitiveMethodSet(T types.Type, msets *MethodSetCache) []*types.Selection { + isPointerToConcrete := func(T types.Type) bool { + ptr, ok := types.Unalias(T).(*types.Pointer) + return ok && !types.IsInterface(ptr.Elem()) + } + + var result []*types.Selection + mset := msets.MethodSet(T) + if types.IsInterface(T) || isPointerToConcrete(T) { + for i, n := 0, mset.Len(); i < n; i++ { + result = append(result, mset.At(i)) + } + } else { + // T is some other concrete type. + // Report methods of T and *T, preferring those of T. + pmset := msets.MethodSet(types.NewPointer(T)) + for i, n := 0, pmset.Len(); i < n; i++ { + meth := pmset.At(i) + if m := mset.Lookup(meth.Obj().Pkg(), meth.Obj().Name()); m != nil { + meth = m + } + result = append(result, meth) + } + + } + return result +} diff --git a/vendor/golang.org/x/tools/internal/aliases/aliases.go b/vendor/golang.org/x/tools/internal/aliases/aliases.go index c24c2eee45..b9425f5a20 100644 --- a/vendor/golang.org/x/tools/internal/aliases/aliases.go +++ b/vendor/golang.org/x/tools/internal/aliases/aliases.go @@ -22,11 +22,17 @@ import ( // 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 { +// +// Precondition: enabled || len(tparams)==0. +// If materialized aliases are disabled, there must not be any type parameters. +func NewAlias(enabled bool, pos token.Pos, pkg *types.Package, name string, rhs types.Type, tparams []*types.TypeParam) *types.TypeName { if enabled { tname := types.NewTypeName(pos, pkg, name, nil) - newAlias(tname, rhs) + SetTypeParams(types.NewAlias(tname, rhs), tparams) return tname } + if len(tparams) > 0 { + panic("cannot create an alias with type parameters when gotypesalias is not enabled") + } 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 deleted file mode 100644 index 6652f7db0f..0000000000 --- a/vendor/golang.org/x/tools/internal/aliases/aliases_go121.go +++ /dev/null @@ -1,35 +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. - -//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") } -func TypeParams(alias *Alias) *types.TypeParamList { panic("unreachable") } -func SetTypeParams(alias *Alias, tparams []*types.TypeParam) { panic("unreachable") } -func TypeArgs(alias *Alias) *types.TypeList { panic("unreachable") } -func Origin(alias *Alias) *Alias { 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 index 3ef1afeb40..7716a3331d 100644 --- a/vendor/golang.org/x/tools/internal/aliases/aliases_go122.go +++ b/vendor/golang.org/x/tools/internal/aliases/aliases_go122.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.22 -// +build go1.22 - package aliases import ( @@ -14,22 +11,19 @@ import ( "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 { +func Rhs(alias *types.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) + return types.Unalias(alias) } // TypeParams returns the type parameter list of the alias. -func TypeParams(alias *Alias) *types.TypeParamList { +func TypeParams(alias *types.Alias) *types.TypeParamList { if alias, ok := any(alias).(interface{ TypeParams() *types.TypeParamList }); ok { return alias.TypeParams() // go1.23+ } @@ -37,7 +31,7 @@ func TypeParams(alias *Alias) *types.TypeParamList { } // SetTypeParams sets the type parameters of the alias type. -func SetTypeParams(alias *Alias, tparams []*types.TypeParam) { +func SetTypeParams(alias *types.Alias, tparams []*types.TypeParam) { if alias, ok := any(alias).(interface { SetTypeParams(tparams []*types.TypeParam) }); ok { @@ -48,7 +42,7 @@ func SetTypeParams(alias *Alias, tparams []*types.TypeParam) { } // TypeArgs returns the type arguments used to instantiate the Alias type. -func TypeArgs(alias *Alias) *types.TypeList { +func TypeArgs(alias *types.Alias) *types.TypeList { if alias, ok := any(alias).(interface{ TypeArgs() *types.TypeList }); ok { return alias.TypeArgs() // go1.23+ } @@ -57,26 +51,13 @@ func TypeArgs(alias *Alias) *types.TypeList { // Origin returns the generic Alias type of which alias is an instance. // If alias is not an instance of a generic alias, Origin returns alias. -func Origin(alias *Alias) *Alias { +func Origin(alias *types.Alias) *types.Alias { if alias, ok := any(alias).(interface{ Origin() *types.Alias }); ok { return alias.Origin() // go1.23+ } return alias // not an instance of a generic alias (go1.22) } -// 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. @@ -92,7 +73,7 @@ func Enabled() bool { // 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) + f, _ := parser.ParseFile(fset, "a.go", "package p; type A = int", parser.SkipObjectResolution) 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/gcimporter/bimport.go b/vendor/golang.org/x/tools/internal/gcimporter/bimport.go index d98b0db2a9..d79a605ed1 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/bimport.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/bimport.go @@ -87,64 +87,3 @@ func chanDir(d int) types.ChanDir { return 0 } } - -var predeclOnce sync.Once -var predecl []types.Type // initialized lazily - -func predeclared() []types.Type { - predeclOnce.Do(func() { - // initialize lazily to be sure that all - // elements have been initialized before - predecl = []types.Type{ // basic types - types.Typ[types.Bool], - types.Typ[types.Int], - types.Typ[types.Int8], - types.Typ[types.Int16], - types.Typ[types.Int32], - types.Typ[types.Int64], - types.Typ[types.Uint], - types.Typ[types.Uint8], - types.Typ[types.Uint16], - types.Typ[types.Uint32], - types.Typ[types.Uint64], - types.Typ[types.Uintptr], - types.Typ[types.Float32], - types.Typ[types.Float64], - types.Typ[types.Complex64], - types.Typ[types.Complex128], - types.Typ[types.String], - - // basic type aliases - types.Universe.Lookup("byte").Type(), - types.Universe.Lookup("rune").Type(), - - // error - types.Universe.Lookup("error").Type(), - - // untyped types - types.Typ[types.UntypedBool], - types.Typ[types.UntypedInt], - types.Typ[types.UntypedRune], - types.Typ[types.UntypedFloat], - types.Typ[types.UntypedComplex], - types.Typ[types.UntypedString], - types.Typ[types.UntypedNil], - - // package unsafe - types.Typ[types.UnsafePointer], - - // invalid type - types.Typ[types.Invalid], // only appears in packages with errors - - // used internally by gc; never used by this package or in .a files - anyType{}, - } - predecl = append(predecl, additionalPredeclared()...) - }) - return predecl -} - -type anyType struct{} - -func (t anyType) Underlying() types.Type { return t } -func (t anyType) String() string { return "any" } diff --git a/vendor/golang.org/x/tools/internal/gcimporter/exportdata.go b/vendor/golang.org/x/tools/internal/gcimporter/exportdata.go index f6437feb1c..6f5d8a2139 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/exportdata.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/exportdata.go @@ -39,12 +39,15 @@ func readGopackHeader(r *bufio.Reader) (name string, size int64, err error) { } // FindExportData positions the reader r at the beginning of the -// export data section of an underlying GC-created object/archive +// export data section of an underlying cmd/compile created archive // file by reading from it. The reader must be positioned at the -// start of the file before calling this function. The hdr result -// is the string before the export data, either "$$" or "$$B". -// The size result is the length of the export data in bytes, or -1 if not known. -func FindExportData(r *bufio.Reader) (hdr string, size int64, err error) { +// start of the file before calling this function. +// The size result is the length of the export data in bytes. +// +// This function is needed by [gcexportdata.Read], which must +// accept inputs produced by the last two releases of cmd/compile, +// plus tip. +func FindExportData(r *bufio.Reader) (size int64, err error) { // Read first line to make sure this is an object file. line, err := r.ReadSlice('\n') if err != nil { @@ -52,27 +55,32 @@ func FindExportData(r *bufio.Reader) (hdr string, size int64, err error) { return } - if string(line) == "!\n" { - // Archive file. Scan to __.PKGDEF. - var name string - if name, size, err = readGopackHeader(r); err != nil { - return - } + // Is the first line an archive file signature? + if string(line) != "!\n" { + err = fmt.Errorf("not the start of an archive file (%q)", line) + return + } - // First entry should be __.PKGDEF. - if name != "__.PKGDEF" { - err = fmt.Errorf("go archive is missing __.PKGDEF") - return - } + // Archive file. Scan to __.PKGDEF. + var name string + if name, size, err = readGopackHeader(r); err != nil { + return + } + arsize := size - // Read first line of __.PKGDEF data, so that line - // is once again the first line of the input. - if line, err = r.ReadSlice('\n'); err != nil { - err = fmt.Errorf("can't find export data (%v)", err) - return - } - size -= int64(len(line)) + // First entry should be __.PKGDEF. + if name != "__.PKGDEF" { + err = fmt.Errorf("go archive is missing __.PKGDEF") + return + } + + // Read first line of __.PKGDEF data, so that line + // is once again the first line of the input. + if line, err = r.ReadSlice('\n'); err != nil { + err = fmt.Errorf("can't find export data (%v)", err) + return } + size -= int64(len(line)) // Now at __.PKGDEF in archive or still at beginning of file. // Either way, line should begin with "go object ". @@ -81,8 +89,8 @@ func FindExportData(r *bufio.Reader) (hdr string, size int64, err error) { return } - // Skip over object header to export data. - // Begins after first line starting with $$. + // Skip over object headers to get to the export data section header "$$B\n". + // Object headers are lines that do not start with '$'. for line[0] != '$' { if line, err = r.ReadSlice('\n'); err != nil { err = fmt.Errorf("can't find export data (%v)", err) @@ -90,9 +98,18 @@ func FindExportData(r *bufio.Reader) (hdr string, size int64, err error) { } size -= int64(len(line)) } - hdr = string(line) + + // Check for the binary export data section header "$$B\n". + hdr := string(line) + if hdr != "$$B\n" { + err = fmt.Errorf("unknown export data header: %q", hdr) + return + } + // TODO(taking): Remove end-of-section marker "\n$$\n" from size. + if size < 0 { - size = -1 + err = fmt.Errorf("invalid size (%d) in the archive file: %d bytes remain without section headers (recompile package)", arsize, size) + return } return diff --git a/vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go b/vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go index 39df91124a..dbbca86043 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go @@ -161,6 +161,8 @@ func FindPkg(path, srcDir string) (filename, id string) { // Import imports a gc-generated package given its import path and srcDir, adds // the corresponding package object to the packages map, and returns the object. // The packages map must contain all packages already imported. +// +// TODO(taking): Import is only used in tests. Move to gcimporter_test. func Import(packages map[string]*types.Package, path, srcDir string, lookup func(path string) (io.ReadCloser, error)) (pkg *types.Package, err error) { var rc io.ReadCloser var filename, id string @@ -210,53 +212,50 @@ func Import(packages map[string]*types.Package, path, srcDir string, lookup func } defer rc.Close() - var hdr string var size int64 buf := bufio.NewReader(rc) - if hdr, size, err = FindExportData(buf); err != nil { + if size, err = FindExportData(buf); err != nil { return } - switch hdr { - case "$$B\n": - var data []byte - data, err = io.ReadAll(buf) - if err != nil { - break - } + var data []byte + data, err = io.ReadAll(buf) + if err != nil { + return + } + if len(data) == 0 { + return nil, fmt.Errorf("no data to load a package from for path %s", id) + } - // TODO(gri): allow clients of go/importer to provide a FileSet. - // Or, define a new standard go/types/gcexportdata package. - fset := token.NewFileSet() + // TODO(gri): allow clients of go/importer to provide a FileSet. + // Or, define a new standard go/types/gcexportdata package. + fset := token.NewFileSet() - // Select appropriate importer. - if len(data) > 0 { - switch data[0] { - case 'v', 'c', 'd': // binary, till go1.10 - return nil, fmt.Errorf("binary (%c) import format is no longer supported", data[0]) + // Select appropriate importer. + switch data[0] { + case 'v', 'c', 'd': + // binary: emitted by cmd/compile till go1.10; obsolete. + return nil, fmt.Errorf("binary (%c) import format is no longer supported", data[0]) - case 'i': // indexed, till go1.19 - _, pkg, err := IImportData(fset, packages, data[1:], id) - return pkg, err + case 'i': + // indexed: emitted by cmd/compile till go1.19; + // now used only for serializing go/types. + // See https://github.com/golang/go/issues/69491. + _, pkg, err := IImportData(fset, packages, data[1:], id) + return pkg, err - case 'u': // unified, from go1.20 - _, pkg, err := UImportData(fset, packages, data[1:size], id) - return pkg, err - - default: - l := len(data) - if l > 10 { - l = 10 - } - return nil, fmt.Errorf("unexpected export data with prefix %q for path %s", string(data[:l]), id) - } - } + case 'u': + // unified: emitted by cmd/compile since go1.20. + _, pkg, err := UImportData(fset, packages, data[1:size], id) + return pkg, err default: - err = fmt.Errorf("unknown export data header: %q", hdr) + l := len(data) + if l > 10 { + l = 10 + } + return nil, fmt.Errorf("unexpected export data with prefix %q for path %s", string(data[:l]), id) } - - return } type byPath []*types.Package diff --git a/vendor/golang.org/x/tools/internal/gcimporter/iexport.go b/vendor/golang.org/x/tools/internal/gcimporter/iexport.go index deeb67f315..7dfc31a37d 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/iexport.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/iexport.go @@ -2,9 +2,227 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Indexed binary package export. -// This file was derived from $GOROOT/src/cmd/compile/internal/gc/iexport.go; -// see that file for specification of the format. +// Indexed package export. +// +// The indexed export data format is an evolution of the previous +// binary export data format. Its chief contribution is introducing an +// index table, which allows efficient random access of individual +// declarations and inline function bodies. In turn, this allows +// avoiding unnecessary work for compilation units that import large +// packages. +// +// +// The top-level data format is structured as: +// +// Header struct { +// Tag byte // 'i' +// Version uvarint +// StringSize uvarint +// DataSize uvarint +// } +// +// Strings [StringSize]byte +// Data [DataSize]byte +// +// MainIndex []struct{ +// PkgPath stringOff +// PkgName stringOff +// PkgHeight uvarint +// +// Decls []struct{ +// Name stringOff +// Offset declOff +// } +// } +// +// Fingerprint [8]byte +// +// uvarint means a uint64 written out using uvarint encoding. +// +// []T means a uvarint followed by that many T objects. In other +// words: +// +// Len uvarint +// Elems [Len]T +// +// stringOff means a uvarint that indicates an offset within the +// Strings section. At that offset is another uvarint, followed by +// that many bytes, which form the string value. +// +// declOff means a uvarint that indicates an offset within the Data +// section where the associated declaration can be found. +// +// +// There are five kinds of declarations, distinguished by their first +// byte: +// +// type Var struct { +// Tag byte // 'V' +// Pos Pos +// Type typeOff +// } +// +// type Func struct { +// Tag byte // 'F' or 'G' +// Pos Pos +// TypeParams []typeOff // only present if Tag == 'G' +// Signature Signature +// } +// +// type Const struct { +// Tag byte // 'C' +// Pos Pos +// Value Value +// } +// +// type Type struct { +// Tag byte // 'T' or 'U' +// Pos Pos +// TypeParams []typeOff // only present if Tag == 'U' +// Underlying typeOff +// +// Methods []struct{ // omitted if Underlying is an interface type +// Pos Pos +// Name stringOff +// Recv Param +// Signature Signature +// } +// } +// +// type Alias struct { +// Tag byte // 'A' or 'B' +// Pos Pos +// TypeParams []typeOff // only present if Tag == 'B' +// Type typeOff +// } +// +// // "Automatic" declaration of each typeparam +// type TypeParam struct { +// Tag byte // 'P' +// Pos Pos +// Implicit bool +// Constraint typeOff +// } +// +// typeOff means a uvarint that either indicates a predeclared type, +// or an offset into the Data section. If the uvarint is less than +// predeclReserved, then it indicates the index into the predeclared +// types list (see predeclared in bexport.go for order). Otherwise, +// subtracting predeclReserved yields the offset of a type descriptor. +// +// Value means a type, kind, and type-specific value. See +// (*exportWriter).value for details. +// +// +// There are twelve kinds of type descriptors, distinguished by an itag: +// +// type DefinedType struct { +// Tag itag // definedType +// Name stringOff +// PkgPath stringOff +// } +// +// type PointerType struct { +// Tag itag // pointerType +// Elem typeOff +// } +// +// type SliceType struct { +// Tag itag // sliceType +// Elem typeOff +// } +// +// type ArrayType struct { +// Tag itag // arrayType +// Len uint64 +// Elem typeOff +// } +// +// type ChanType struct { +// Tag itag // chanType +// Dir uint64 // 1 RecvOnly; 2 SendOnly; 3 SendRecv +// Elem typeOff +// } +// +// type MapType struct { +// Tag itag // mapType +// Key typeOff +// Elem typeOff +// } +// +// type FuncType struct { +// Tag itag // signatureType +// PkgPath stringOff +// Signature Signature +// } +// +// type StructType struct { +// Tag itag // structType +// PkgPath stringOff +// Fields []struct { +// Pos Pos +// Name stringOff +// Type typeOff +// Embedded bool +// Note stringOff +// } +// } +// +// type InterfaceType struct { +// Tag itag // interfaceType +// PkgPath stringOff +// Embeddeds []struct { +// Pos Pos +// Type typeOff +// } +// Methods []struct { +// Pos Pos +// Name stringOff +// Signature Signature +// } +// } +// +// // Reference to a type param declaration +// type TypeParamType struct { +// Tag itag // typeParamType +// Name stringOff +// PkgPath stringOff +// } +// +// // Instantiation of a generic type (like List[T2] or List[int]) +// type InstanceType struct { +// Tag itag // instanceType +// Pos pos +// TypeArgs []typeOff +// BaseType typeOff +// } +// +// type UnionType struct { +// Tag itag // interfaceType +// Terms []struct { +// tilde bool +// Type typeOff +// } +// } +// +// +// +// type Signature struct { +// Params []Param +// Results []Param +// Variadic bool // omitted if Results is empty +// } +// +// type Param struct { +// Pos Pos +// Name stringOff +// Type typOff +// } +// +// +// Pos encodes a file:line:column triple, incorporating a simple delta +// encoding scheme within a data object. See exportWriter.pos for +// details. package gcimporter @@ -24,11 +242,30 @@ import ( "golang.org/x/tools/go/types/objectpath" "golang.org/x/tools/internal/aliases" - "golang.org/x/tools/internal/tokeninternal" ) // IExportShallow encodes "shallow" export data for the specified package. // +// For types, we use "shallow" export data. Historically, the Go +// compiler always produced a summary of the types for a given package +// that included types from other packages that it indirectly +// referenced: "deep" export data. This had the advantage that the +// compiler (and analogous tools such as gopls) need only load one +// file per direct import. However, it meant that the files tended to +// get larger based on the level of the package in the import +// graph. For example, higher-level packages in the kubernetes module +// have over 1MB of "deep" export data, even when they have almost no +// content of their own, merely because they mention a major type that +// references many others. In pathological cases the export data was +// 300x larger than the source for a package due to this quadratic +// growth. +// +// "Shallow" export data means that the serialized types describe only +// a single package. If those types mention types from other packages, +// the type checker may need to request additional packages beyond +// just the direct imports. Type information for the entire transitive +// closure of imports is provided (lazily) by the DAG. +// // No promises are made about the encoding other than that it can be decoded by // the same version of IIExportShallow. If you plan to save export data in the // file system, be sure to include a cryptographic digest of the executable in @@ -51,8 +288,8 @@ func IExportShallow(fset *token.FileSet, pkg *types.Package, reportf ReportFunc) } // IImportShallow decodes "shallow" types.Package data encoded by -// IExportShallow in the same executable. This function cannot import data from -// cmd/compile or gcexportdata.Write. +// [IExportShallow] in the same executable. This function cannot import data +// from cmd/compile or gcexportdata.Write. // // The importer calls getPackages to obtain package symbols for all // packages mentioned in the export data, including the one being @@ -223,7 +460,7 @@ func (p *iexporter) encodeFile(w *intWriter, file *token.File, needed []uint64) // Sort the set of needed offsets. Duplicates are harmless. sort.Slice(needed, func(i, j int) bool { return needed[i] < needed[j] }) - lines := tokeninternal.GetLines(file) // byte offset of each line start + lines := file.Lines() // byte offset of each line start w.uint64(uint64(len(lines))) // Rather than record the entire array of line start offsets, @@ -507,13 +744,13 @@ func (p *iexporter) doDecl(obj types.Object) { case *types.TypeName: t := obj.Type() - if tparam, ok := aliases.Unalias(t).(*types.TypeParam); ok { + if tparam, ok := types.Unalias(t).(*types.TypeParam); ok { w.tag(typeParamTag) w.pos(obj.Pos()) constraint := tparam.Constraint() if p.version >= iexportVersionGo1_18 { implicit := false - if iface, _ := aliases.Unalias(constraint).(*types.Interface); iface != nil { + if iface, _ := types.Unalias(constraint).(*types.Interface); iface != nil { implicit = iface.IsImplicit() } w.bool(implicit) @@ -523,9 +760,22 @@ func (p *iexporter) doDecl(obj types.Object) { } if obj.IsAlias() { - w.tag(aliasTag) + alias, materialized := t.(*types.Alias) // may fail when aliases are not enabled + + var tparams *types.TypeParamList + if materialized { + tparams = aliases.TypeParams(alias) + } + if tparams.Len() == 0 { + w.tag(aliasTag) + } else { + w.tag(genericAliasTag) + } w.pos(obj.Pos()) - if alias, ok := t.(*aliases.Alias); ok { + if tparams.Len() > 0 { + w.tparamList(obj.Name(), tparams, obj.Pkg()) + } + if materialized { // Preserve materialized aliases, // even of non-exported types. t = aliases.Rhs(alias) @@ -744,8 +994,14 @@ 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. + case *types.Alias: + if targs := aliases.TypeArgs(t); targs.Len() > 0 { + w.startType(instanceType) + w.pos(t.Obj().Pos()) + w.typeList(targs, pkg) + w.typ(aliases.Origin(t), pkg) + return + } w.startType(aliasType) w.qualifiedType(t.Obj()) @@ -854,7 +1110,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, _ := aliases.Unalias(ft).(*types.Named); named != nil { + if named, _ := types.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 136aa03653..e260c0e8db 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/iimport.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/iimport.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // Indexed package import. -// See cmd/compile/internal/gc/iexport.go for the export data format. +// See iexport.go for the export data format. // This file is a copy of $GOROOT/src/go/internal/gcimporter/iimport.go. @@ -53,6 +53,7 @@ const ( iexportVersionPosCol = 1 iexportVersionGo1_18 = 2 iexportVersionGenerics = 2 + iexportVersion = iexportVersionGenerics iexportVersionCurrent = 2 ) @@ -540,7 +541,7 @@ func canReuse(def *types.Named, rhs types.Type) bool { if def == nil { return true } - iface, _ := aliases.Unalias(rhs).(*types.Interface) + iface, _ := types.Unalias(rhs).(*types.Interface) if iface == nil { return true } @@ -557,19 +558,28 @@ type importReader struct { prevColumn int64 } +// markBlack is redefined in iimport_go123.go, to work around golang/go#69912. +// +// If TypeNames are not marked black (in the sense of go/types cycle +// detection), they may be mutated when dot-imported. Fix this by punching a +// hole through the type, when compiling with Go 1.23. (The bug has been fixed +// for 1.24, but the fix was not worth back-porting). +var markBlack = func(name *types.TypeName) {} + func (r *importReader) obj(name string) { tag := r.byte() pos := r.pos() switch tag { - case aliasTag: + case aliasTag, genericAliasTag: + var tparams []*types.TypeParam + if tag == genericAliasTag { + tparams = r.tparamList() + } typ := r.typ() - // 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)) + obj := aliases.NewAlias(r.p.aliases, pos, r.currPkg, name, typ, tparams) + markBlack(obj) // workaround for golang/go#69912 + r.declare(obj) case constTag: typ, val := r.value() @@ -589,6 +599,9 @@ func (r *importReader) obj(name string) { // declaration before recursing. obj := types.NewTypeName(pos, r.currPkg, name, nil) named := types.NewNamed(obj, nil, nil) + + markBlack(obj) // workaround for golang/go#69912 + // 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) @@ -615,7 +628,7 @@ func (r *importReader) obj(name string) { if targs.Len() > 0 { rparams = make([]*types.TypeParam, targs.Len()) for i := range rparams { - rparams[i] = aliases.Unalias(targs.At(i)).(*types.TypeParam) + rparams[i] = types.Unalias(targs.At(i)).(*types.TypeParam) } } msig := r.signature(recv, rparams, nil) @@ -645,7 +658,7 @@ func (r *importReader) obj(name string) { } constraint := r.typ() if implicit { - iface, _ := aliases.Unalias(constraint).(*types.Interface) + iface, _ := types.Unalias(constraint).(*types.Interface) if iface == nil { errorf("non-interface constraint marked implicit") } @@ -852,7 +865,7 @@ func (r *importReader) typ() types.Type { } func isInterface(t types.Type) bool { - _, ok := aliases.Unalias(t).(*types.Interface) + _, ok := types.Unalias(t).(*types.Interface) return ok } @@ -862,7 +875,7 @@ func (r *importReader) string() string { return r.p.stringAt(r.uint64()) } func (r *importReader) doType(base *types.Named) (res types.Type) { k := r.kind() if debug { - r.p.trace("importing type %d (base: %s)", k, base) + r.p.trace("importing type %d (base: %v)", k, base) r.p.indent++ defer func() { r.p.indent-- @@ -959,7 +972,7 @@ func (r *importReader) doType(base *types.Named) (res types.Type) { methods[i] = method } - typ := newInterface(methods, embeddeds) + typ := types.NewInterfaceType(methods, embeddeds) r.p.interfaceList = append(r.p.interfaceList, typ) return typ @@ -1051,7 +1064,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] = aliases.Unalias(r.typ()).(*types.TypeParam) + xs[i] = types.Unalias(r.typ()).(*types.TypeParam) } return xs } diff --git a/vendor/golang.org/x/tools/internal/gcimporter/iimport_go122.go b/vendor/golang.org/x/tools/internal/gcimporter/iimport_go122.go new file mode 100644 index 0000000000..7586bfaca6 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/gcimporter/iimport_go122.go @@ -0,0 +1,53 @@ +// 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 && !go1.24 + +package gcimporter + +import ( + "go/token" + "go/types" + "unsafe" +) + +// TODO(rfindley): delete this workaround once go1.24 is assured. + +func init() { + // Update markBlack so that it correctly sets the color + // of imported TypeNames. + // + // See the doc comment for markBlack for details. + + type color uint32 + const ( + white color = iota + black + grey + ) + type object struct { + _ *types.Scope + _ token.Pos + _ *types.Package + _ string + _ types.Type + _ uint32 + color_ color + _ token.Pos + } + type typeName struct { + object + } + + // If the size of types.TypeName changes, this will fail to compile. + const delta = int64(unsafe.Sizeof(typeName{})) - int64(unsafe.Sizeof(types.TypeName{})) + var _ [-delta * delta]int + + markBlack = func(obj *types.TypeName) { + type uP = unsafe.Pointer + var ptr *typeName + *(*uP)(uP(&ptr)) = uP(obj) + ptr.color_ = black + } +} diff --git a/vendor/golang.org/x/tools/internal/gcimporter/newInterface10.go b/vendor/golang.org/x/tools/internal/gcimporter/newInterface10.go deleted file mode 100644 index 8b163e3d05..0000000000 --- a/vendor/golang.org/x/tools/internal/gcimporter/newInterface10.go +++ /dev/null @@ -1,22 +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 !go1.11 -// +build !go1.11 - -package gcimporter - -import "go/types" - -func newInterface(methods []*types.Func, embeddeds []types.Type) *types.Interface { - named := make([]*types.Named, len(embeddeds)) - for i, e := range embeddeds { - var ok bool - named[i], ok = e.(*types.Named) - if !ok { - panic("embedding of non-defined interfaces in interfaces is not supported before Go 1.11") - } - } - return types.NewInterface(methods, named) -} diff --git a/vendor/golang.org/x/tools/internal/gcimporter/newInterface11.go b/vendor/golang.org/x/tools/internal/gcimporter/newInterface11.go deleted file mode 100644 index 49984f40fd..0000000000 --- a/vendor/golang.org/x/tools/internal/gcimporter/newInterface11.go +++ /dev/null @@ -1,14 +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 go1.11 -// +build go1.11 - -package gcimporter - -import "go/types" - -func newInterface(methods []*types.Func, embeddeds []types.Type) *types.Interface { - return types.NewInterfaceType(methods, embeddeds) -} diff --git a/vendor/golang.org/x/tools/internal/gcimporter/predeclared.go b/vendor/golang.org/x/tools/internal/gcimporter/predeclared.go new file mode 100644 index 0000000000..907c8557a5 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/gcimporter/predeclared.go @@ -0,0 +1,91 @@ +// 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 gcimporter + +import ( + "go/types" + "sync" +) + +// predecl is a cache for the predeclared types in types.Universe. +// +// Cache a distinct result based on the runtime value of any. +// The pointer value of the any type varies based on GODEBUG settings. +var predeclMu sync.Mutex +var predecl map[types.Type][]types.Type + +func predeclared() []types.Type { + anyt := types.Universe.Lookup("any").Type() + + predeclMu.Lock() + defer predeclMu.Unlock() + + if pre, ok := predecl[anyt]; ok { + return pre + } + + if predecl == nil { + predecl = make(map[types.Type][]types.Type) + } + + decls := []types.Type{ // basic types + types.Typ[types.Bool], + types.Typ[types.Int], + types.Typ[types.Int8], + types.Typ[types.Int16], + types.Typ[types.Int32], + types.Typ[types.Int64], + types.Typ[types.Uint], + types.Typ[types.Uint8], + types.Typ[types.Uint16], + types.Typ[types.Uint32], + types.Typ[types.Uint64], + types.Typ[types.Uintptr], + types.Typ[types.Float32], + types.Typ[types.Float64], + types.Typ[types.Complex64], + types.Typ[types.Complex128], + types.Typ[types.String], + + // basic type aliases + types.Universe.Lookup("byte").Type(), + types.Universe.Lookup("rune").Type(), + + // error + types.Universe.Lookup("error").Type(), + + // untyped types + types.Typ[types.UntypedBool], + types.Typ[types.UntypedInt], + types.Typ[types.UntypedRune], + types.Typ[types.UntypedFloat], + types.Typ[types.UntypedComplex], + types.Typ[types.UntypedString], + types.Typ[types.UntypedNil], + + // package unsafe + types.Typ[types.UnsafePointer], + + // invalid type + types.Typ[types.Invalid], // only appears in packages with errors + + // used internally by gc; never used by this package or in .a files + anyType{}, + + // comparable + types.Universe.Lookup("comparable").Type(), + + // any + anyt, + } + + predecl[anyt] = decls + return decls +} + +type anyType struct{} + +func (t anyType) Underlying() types.Type { return t } +func (t anyType) String() string { return "any" } diff --git a/vendor/golang.org/x/tools/internal/gcimporter/support_go118.go b/vendor/golang.org/x/tools/internal/gcimporter/support_go118.go deleted file mode 100644 index 0cd3b91b65..0000000000 --- a/vendor/golang.org/x/tools/internal/gcimporter/support_go118.go +++ /dev/null @@ -1,34 +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 gcimporter - -import "go/types" - -const iexportVersion = iexportVersionGenerics - -// additionalPredeclared returns additional predeclared types in go.1.18. -func additionalPredeclared() []types.Type { - return []types.Type{ - // comparable - types.Universe.Lookup("comparable").Type(), - - // any - types.Universe.Lookup("any").Type(), - } -} - -// See cmd/compile/internal/types.SplitVargenSuffix. -func splitVargenSuffix(name string) (base, suffix string) { - i := len(name) - for i > 0 && name[i-1] >= '0' && name[i-1] <= '9' { - i-- - } - const dot = "·" - if i >= len(dot) && name[i-len(dot):i] == dot { - i -= len(dot) - return name[:i], name[i:] - } - return name, "" -} diff --git a/vendor/golang.org/x/tools/internal/gcimporter/unified_no.go b/vendor/golang.org/x/tools/internal/gcimporter/unified_no.go deleted file mode 100644 index 38b624cada..0000000000 --- a/vendor/golang.org/x/tools/internal/gcimporter/unified_no.go +++ /dev/null @@ -1,10 +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 !goexperiment.unified -// +build !goexperiment.unified - -package gcimporter - -const unifiedIR = false diff --git a/vendor/golang.org/x/tools/internal/gcimporter/unified_yes.go b/vendor/golang.org/x/tools/internal/gcimporter/unified_yes.go deleted file mode 100644 index b5118d0b3a..0000000000 --- a/vendor/golang.org/x/tools/internal/gcimporter/unified_yes.go +++ /dev/null @@ -1,10 +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 goexperiment.unified -// +build goexperiment.unified - -package gcimporter - -const unifiedIR = true 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 2c07706887..1db408613c 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/ureader_yes.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/ureader_yes.go @@ -52,8 +52,7 @@ func (pr *pkgReader) later(fn func()) { // See cmd/compile/internal/noder.derivedInfo. type derivedInfo struct { - idx pkgbits.Index - needed bool + idx pkgbits.Index } // See cmd/compile/internal/noder.typeInfo. @@ -110,13 +109,17 @@ func readUnifiedPackage(fset *token.FileSet, ctxt *types.Context, imports map[st r := pr.newReader(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic) pkg := r.pkg() - r.Bool() // has init + if r.Version().Has(pkgbits.HasInit) { + r.Bool() + } for i, n := 0, r.Len(); i < n; i++ { // As if r.obj(), but avoiding the Scope.Lookup call, // to avoid eager loading of imports. r.Sync(pkgbits.SyncObject) - assert(!r.Bool()) + if r.Version().Has(pkgbits.DerivedFuncInstance) { + assert(!r.Bool()) + } r.p.objIdx(r.Reloc(pkgbits.RelocObj)) assert(r.Len() == 0) } @@ -165,7 +168,7 @@ type readerDict struct { // tparams is a slice of the constructed TypeParams for the element. tparams []*types.TypeParam - // devived is a slice of types derived from tparams, which may be + // derived is a slice of types derived from tparams, which may be // instantiated while reading the current element. derived []derivedInfo derivedTypes []types.Type // lazily instantiated from derived @@ -471,7 +474,9 @@ func (r *reader) param() *types.Var { func (r *reader) obj() (types.Object, []types.Type) { r.Sync(pkgbits.SyncObject) - assert(!r.Bool()) + if r.Version().Has(pkgbits.DerivedFuncInstance) { + assert(!r.Bool()) + } pkg, name := r.p.objIdx(r.Reloc(pkgbits.RelocObj)) obj := pkgScope(pkg).Lookup(name) @@ -525,8 +530,12 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) { case pkgbits.ObjAlias: pos := r.pos() + var tparams []*types.TypeParam + if r.Version().Has(pkgbits.AliasTypeParamNames) { + tparams = r.typeParamNames() + } typ := r.typ() - declare(aliases.NewAlias(r.p.aliases, pos, objPkg, objName, typ)) + declare(aliases.NewAlias(r.p.aliases, pos, objPkg, objName, typ, tparams)) case pkgbits.ObjConst: pos := r.pos() @@ -553,7 +562,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 := aliases.Unalias(underlying).(*types.Interface); ok && iface.NumExplicitMethods() != 0 { + if iface, ok := types.Unalias(underlying).(*types.Interface); ok && iface.NumExplicitMethods() != 0 { methods := make([]*types.Func, iface.NumExplicitMethods()) for i := range methods { fn := iface.ExplicitMethod(i) @@ -632,7 +641,10 @@ func (pr *pkgReader) objDictIdx(idx pkgbits.Index) *readerDict { dict.derived = make([]derivedInfo, r.Len()) dict.derivedTypes = make([]types.Type, len(dict.derived)) for i := range dict.derived { - dict.derived[i] = derivedInfo{r.Reloc(pkgbits.RelocType), r.Bool()} + dict.derived[i] = derivedInfo{idx: r.Reloc(pkgbits.RelocType)} + if r.Version().Has(pkgbits.DerivedInfoNeeded) { + assert(!r.Bool()) + } } pr.retireReader(r) @@ -726,3 +738,17 @@ func pkgScope(pkg *types.Package) *types.Scope { } return types.Universe } + +// See cmd/compile/internal/types.SplitVargenSuffix. +func splitVargenSuffix(name string) (base, suffix string) { + i := len(name) + for i > 0 && name[i-1] >= '0' && name[i-1] <= '9' { + i-- + } + const dot = "·" + if i >= len(dot) && name[i-len(dot):i] == dot { + i -= len(dot) + return name[:i], name[i:] + } + return name, "" +} diff --git a/vendor/golang.org/x/tools/internal/gocommand/invoke.go b/vendor/golang.org/x/tools/internal/gocommand/invoke.go index 2e59ff8558..e333efc87f 100644 --- a/vendor/golang.org/x/tools/internal/gocommand/invoke.go +++ b/vendor/golang.org/x/tools/internal/gocommand/invoke.go @@ -16,7 +16,6 @@ import ( "os" "os/exec" "path/filepath" - "reflect" "regexp" "runtime" "strconv" @@ -250,16 +249,13 @@ func (i *Invocation) run(ctx context.Context, stdout, stderr io.Writer) error { cmd.Stdout = stdout cmd.Stderr = stderr - // cmd.WaitDelay was added only in go1.20 (see #50436). - if waitDelay := reflect.ValueOf(cmd).Elem().FieldByName("WaitDelay"); waitDelay.IsValid() { - // https://go.dev/issue/59541: don't wait forever copying stderr - // after the command has exited. - // After CL 484741 we copy stdout manually, so we we'll stop reading that as - // soon as ctx is done. However, we also don't want to wait around forever - // for stderr. Give a much-longer-than-reasonable delay and then assume that - // something has wedged in the kernel or runtime. - waitDelay.Set(reflect.ValueOf(30 * time.Second)) - } + // https://go.dev/issue/59541: don't wait forever copying stderr + // after the command has exited. + // After CL 484741 we copy stdout manually, so we we'll stop reading that as + // soon as ctx is done. However, we also don't want to wait around forever + // for stderr. Give a much-longer-than-reasonable delay and then assume that + // something has wedged in the kernel or runtime. + cmd.WaitDelay = 30 * time.Second // The cwd gets resolved to the real path. On Darwin, where // /tmp is a symlink, this breaks anything that expects the diff --git a/vendor/golang.org/x/tools/internal/packagesinternal/packages.go b/vendor/golang.org/x/tools/internal/packagesinternal/packages.go index 44719de173..66e69b4389 100644 --- a/vendor/golang.org/x/tools/internal/packagesinternal/packages.go +++ b/vendor/golang.org/x/tools/internal/packagesinternal/packages.go @@ -5,7 +5,6 @@ // Package packagesinternal exposes internal-only fields from go/packages. package packagesinternal -var GetForTest = func(p interface{}) string { return "" } var GetDepsErrors = func(p interface{}) []*PackageError { return nil } type PackageError struct { @@ -16,7 +15,6 @@ type PackageError struct { var TypecheckCgo int var DepsErrors int // must be set as a LoadMode to call GetDepsErrors -var ForTest int // must be set as a LoadMode to call GetForTest var SetModFlag = func(config interface{}, value string) {} var SetModFile = func(config interface{}, value string) {} diff --git a/vendor/golang.org/x/tools/internal/pkgbits/decoder.go b/vendor/golang.org/x/tools/internal/pkgbits/decoder.go index b92e8e6eb3..f6cb37c5c3 100644 --- a/vendor/golang.org/x/tools/internal/pkgbits/decoder.go +++ b/vendor/golang.org/x/tools/internal/pkgbits/decoder.go @@ -21,7 +21,7 @@ import ( // export data. type PkgDecoder struct { // version is the file format version. - version uint32 + version Version // sync indicates whether the file uses sync markers. sync bool @@ -68,8 +68,6 @@ func (pr *PkgDecoder) SyncMarkers() bool { return pr.sync } // NewPkgDecoder returns a PkgDecoder initialized to read the Unified // IR export data from input. pkgPath is the package path for the // compilation unit that produced the export data. -// -// TODO(mdempsky): Remove pkgPath parameter; unneeded since CL 391014. func NewPkgDecoder(pkgPath, input string) PkgDecoder { pr := PkgDecoder{ pkgPath: pkgPath, @@ -80,14 +78,15 @@ func NewPkgDecoder(pkgPath, input string) PkgDecoder { r := strings.NewReader(input) - assert(binary.Read(r, binary.LittleEndian, &pr.version) == nil) + var ver uint32 + assert(binary.Read(r, binary.LittleEndian, &ver) == nil) + pr.version = Version(ver) - switch pr.version { - default: - panic(fmt.Errorf("unsupported version: %v", pr.version)) - case 0: - // no flags - case 1: + if pr.version >= numVersions { + panic(fmt.Errorf("cannot decode %q, export data version %d is greater than maximum supported version %d", pkgPath, pr.version, numVersions-1)) + } + + if pr.version.Has(Flags) { var flags uint32 assert(binary.Read(r, binary.LittleEndian, &flags) == nil) pr.sync = flags&flagSyncMarkers != 0 @@ -102,7 +101,9 @@ func NewPkgDecoder(pkgPath, input string) PkgDecoder { assert(err == nil) pr.elemData = input[pos:] - assert(len(pr.elemData)-8 == int(pr.elemEnds[len(pr.elemEnds)-1])) + + const fingerprintSize = 8 + assert(len(pr.elemData)-fingerprintSize == int(pr.elemEnds[len(pr.elemEnds)-1])) return pr } @@ -136,7 +137,7 @@ func (pr *PkgDecoder) AbsIdx(k RelocKind, idx Index) int { absIdx += int(pr.elemEndsEnds[k-1]) } if absIdx >= int(pr.elemEndsEnds[k]) { - errorf("%v:%v is out of bounds; %v", k, idx, pr.elemEndsEnds) + panicf("%v:%v is out of bounds; %v", k, idx, pr.elemEndsEnds) } return absIdx } @@ -193,9 +194,7 @@ func (pr *PkgDecoder) NewDecoderRaw(k RelocKind, idx Index) Decoder { Idx: idx, } - // TODO(mdempsky) r.data.Reset(...) after #44505 is resolved. - r.Data = *strings.NewReader(pr.DataIdx(k, idx)) - + r.Data.Reset(pr.DataIdx(k, idx)) r.Sync(SyncRelocs) r.Relocs = make([]RelocEnt, r.Len()) for i := range r.Relocs { @@ -244,7 +243,7 @@ type Decoder struct { func (r *Decoder) checkErr(err error) { if err != nil { - errorf("unexpected decoding error: %w", err) + panicf("unexpected decoding error: %w", err) } } @@ -515,3 +514,6 @@ func (pr *PkgDecoder) PeekObj(idx Index) (string, string, CodeObj) { return path, name, tag } + +// Version reports the version of the bitstream. +func (w *Decoder) Version() Version { return w.common.version } diff --git a/vendor/golang.org/x/tools/internal/pkgbits/encoder.go b/vendor/golang.org/x/tools/internal/pkgbits/encoder.go index 6482617a4f..c17a12399d 100644 --- a/vendor/golang.org/x/tools/internal/pkgbits/encoder.go +++ b/vendor/golang.org/x/tools/internal/pkgbits/encoder.go @@ -12,18 +12,15 @@ import ( "io" "math/big" "runtime" + "strings" ) -// currentVersion is the current version number. -// -// - v0: initial prototype -// -// - v1: adds the flags uint32 word -const currentVersion uint32 = 1 - // A PkgEncoder provides methods for encoding a package's Unified IR // export data. type PkgEncoder struct { + // version of the bitstream. + version Version + // elems holds the bitstream for previously encoded elements. elems [numRelocs][]string @@ -47,8 +44,9 @@ func (pw *PkgEncoder) SyncMarkers() bool { return pw.syncFrames >= 0 } // export data files, but can help diagnosing desync errors in // higher-level Unified IR reader/writer code. If syncFrames is // negative, then sync markers are omitted entirely. -func NewPkgEncoder(syncFrames int) PkgEncoder { +func NewPkgEncoder(version Version, syncFrames int) PkgEncoder { return PkgEncoder{ + version: version, stringsIdx: make(map[string]Index), syncFrames: syncFrames, } @@ -64,13 +62,15 @@ func (pw *PkgEncoder) DumpTo(out0 io.Writer) (fingerprint [8]byte) { assert(binary.Write(out, binary.LittleEndian, x) == nil) } - writeUint32(currentVersion) + writeUint32(uint32(pw.version)) - var flags uint32 - if pw.SyncMarkers() { - flags |= flagSyncMarkers + if pw.version.Has(Flags) { + var flags uint32 + if pw.SyncMarkers() { + flags |= flagSyncMarkers + } + writeUint32(flags) } - writeUint32(flags) // Write elemEndsEnds. var sum uint32 @@ -159,7 +159,7 @@ type Encoder struct { // Flush finalizes the element's bitstream and returns its Index. func (w *Encoder) Flush() Index { - var sb bytes.Buffer // TODO(mdempsky): strings.Builder after #44505 is resolved + var sb strings.Builder // Backup the data so we write the relocations at the front. var tmp bytes.Buffer @@ -189,7 +189,7 @@ func (w *Encoder) Flush() Index { func (w *Encoder) checkErr(err error) { if err != nil { - errorf("unexpected encoding error: %v", err) + panicf("unexpected encoding error: %v", err) } } @@ -320,8 +320,14 @@ func (w *Encoder) Code(c Code) { // section (if not already present), and then writing a relocation // into the element bitstream. func (w *Encoder) String(s string) { + w.StringRef(w.p.StringIdx(s)) +} + +// StringRef writes a reference to the given index, which must be a +// previously encoded string value. +func (w *Encoder) StringRef(idx Index) { w.Sync(SyncString) - w.Reloc(RelocString, w.p.StringIdx(s)) + w.Reloc(RelocString, idx) } // Strings encodes and writes a variable-length slice of strings into @@ -348,7 +354,7 @@ func (w *Encoder) Value(val constant.Value) { func (w *Encoder) scalar(val constant.Value) { switch v := constant.Val(val).(type) { default: - errorf("unhandled %v (%v)", val, val.Kind()) + panicf("unhandled %v (%v)", val, val.Kind()) case bool: w.Code(ValBool) w.Bool(v) @@ -381,3 +387,6 @@ func (w *Encoder) bigFloat(v *big.Float) { b := v.Append(nil, 'p', -1) w.String(string(b)) // TODO: More efficient encoding. } + +// Version reports the version of the bitstream. +func (w *Encoder) Version() Version { return w.p.version } diff --git a/vendor/golang.org/x/tools/internal/pkgbits/frames_go1.go b/vendor/golang.org/x/tools/internal/pkgbits/frames_go1.go deleted file mode 100644 index 5294f6a63e..0000000000 --- a/vendor/golang.org/x/tools/internal/pkgbits/frames_go1.go +++ /dev/null @@ -1,21 +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.7 -// +build !go1.7 - -// TODO(mdempsky): Remove after #44505 is resolved - -package pkgbits - -import "runtime" - -func walkFrames(pcs []uintptr, visit frameVisitor) { - for _, pc := range pcs { - fn := runtime.FuncForPC(pc) - file, line := fn.FileLine(pc) - - visit(file, line, fn.Name(), pc-fn.Entry()) - } -} diff --git a/vendor/golang.org/x/tools/internal/pkgbits/frames_go17.go b/vendor/golang.org/x/tools/internal/pkgbits/frames_go17.go deleted file mode 100644 index 2324ae7adf..0000000000 --- a/vendor/golang.org/x/tools/internal/pkgbits/frames_go17.go +++ /dev/null @@ -1,28 +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.7 -// +build go1.7 - -package pkgbits - -import "runtime" - -// walkFrames calls visit for each call frame represented by pcs. -// -// pcs should be a slice of PCs, as returned by runtime.Callers. -func walkFrames(pcs []uintptr, visit frameVisitor) { - if len(pcs) == 0 { - return - } - - frames := runtime.CallersFrames(pcs) - for { - frame, more := frames.Next() - visit(frame.File, frame.Line, frame.Function, frame.PC-frame.Entry) - if !more { - return - } - } -} diff --git a/vendor/golang.org/x/tools/internal/pkgbits/support.go b/vendor/golang.org/x/tools/internal/pkgbits/support.go index ad26d3b28c..50534a2955 100644 --- a/vendor/golang.org/x/tools/internal/pkgbits/support.go +++ b/vendor/golang.org/x/tools/internal/pkgbits/support.go @@ -12,6 +12,6 @@ func assert(b bool) { } } -func errorf(format string, args ...interface{}) { +func panicf(format string, args ...any) { panic(fmt.Errorf(format, args...)) } diff --git a/vendor/golang.org/x/tools/internal/pkgbits/sync.go b/vendor/golang.org/x/tools/internal/pkgbits/sync.go index 5bd51ef717..1520b73afb 100644 --- a/vendor/golang.org/x/tools/internal/pkgbits/sync.go +++ b/vendor/golang.org/x/tools/internal/pkgbits/sync.go @@ -6,6 +6,7 @@ package pkgbits import ( "fmt" + "runtime" "strings" ) @@ -23,6 +24,24 @@ func fmtFrames(pcs ...uintptr) []string { type frameVisitor func(file string, line int, name string, offset uintptr) +// walkFrames calls visit for each call frame represented by pcs. +// +// pcs should be a slice of PCs, as returned by runtime.Callers. +func walkFrames(pcs []uintptr, visit frameVisitor) { + if len(pcs) == 0 { + return + } + + frames := runtime.CallersFrames(pcs) + for { + frame, more := frames.Next() + visit(frame.File, frame.Line, frame.Function, frame.PC-frame.Entry) + if !more { + return + } + } +} + // SyncMarker is an enum type that represents markers that may be // written to export data to ensure the reader and writer stay // synchronized. @@ -110,4 +129,8 @@ const ( SyncStmtsEnd SyncLabel SyncOptLabel + + SyncMultiExpr + SyncRType + SyncConvRTTI ) diff --git a/vendor/golang.org/x/tools/internal/pkgbits/syncmarker_string.go b/vendor/golang.org/x/tools/internal/pkgbits/syncmarker_string.go index 4a5b0ca5f2..582ad56d3e 100644 --- a/vendor/golang.org/x/tools/internal/pkgbits/syncmarker_string.go +++ b/vendor/golang.org/x/tools/internal/pkgbits/syncmarker_string.go @@ -74,11 +74,14 @@ func _() { _ = x[SyncStmtsEnd-64] _ = x[SyncLabel-65] _ = x[SyncOptLabel-66] + _ = x[SyncMultiExpr-67] + _ = x[SyncRType-68] + _ = x[SyncConvRTTI-69] } -const _SyncMarker_name = "EOFBoolInt64Uint64StringValueValRelocsRelocUseRelocPublicPosPosBaseObjectObject1PkgPkgDefMethodTypeTypeIdxTypeParamNamesSignatureParamsParamCodeObjSymLocalIdentSelectorPrivateFuncExtVarExtTypeExtPragmaExprListExprsExprExprTypeAssignOpFuncLitCompLitDeclFuncBodyOpenScopeCloseScopeCloseAnotherScopeDeclNamesDeclNameStmtsBlockStmtIfStmtForStmtSwitchStmtRangeStmtCaseClauseCommClauseSelectStmtDeclsLabeledStmtUseObjLocalAddLocalLinknameStmt1StmtsEndLabelOptLabel" +const _SyncMarker_name = "EOFBoolInt64Uint64StringValueValRelocsRelocUseRelocPublicPosPosBaseObjectObject1PkgPkgDefMethodTypeTypeIdxTypeParamNamesSignatureParamsParamCodeObjSymLocalIdentSelectorPrivateFuncExtVarExtTypeExtPragmaExprListExprsExprExprTypeAssignOpFuncLitCompLitDeclFuncBodyOpenScopeCloseScopeCloseAnotherScopeDeclNamesDeclNameStmtsBlockStmtIfStmtForStmtSwitchStmtRangeStmtCaseClauseCommClauseSelectStmtDeclsLabeledStmtUseObjLocalAddLocalLinknameStmt1StmtsEndLabelOptLabelMultiExprRTypeConvRTTI" -var _SyncMarker_index = [...]uint16{0, 3, 7, 12, 18, 24, 29, 32, 38, 43, 51, 57, 60, 67, 73, 80, 83, 89, 95, 99, 106, 120, 129, 135, 140, 147, 150, 160, 168, 175, 182, 188, 195, 201, 209, 214, 218, 226, 232, 234, 241, 248, 252, 260, 269, 279, 296, 305, 313, 318, 327, 333, 340, 350, 359, 369, 379, 389, 394, 405, 416, 424, 432, 437, 445, 450, 458} +var _SyncMarker_index = [...]uint16{0, 3, 7, 12, 18, 24, 29, 32, 38, 43, 51, 57, 60, 67, 73, 80, 83, 89, 95, 99, 106, 120, 129, 135, 140, 147, 150, 160, 168, 175, 182, 188, 195, 201, 209, 214, 218, 226, 232, 234, 241, 248, 252, 260, 269, 279, 296, 305, 313, 318, 327, 333, 340, 350, 359, 369, 379, 389, 394, 405, 416, 424, 432, 437, 445, 450, 458, 467, 472, 480} func (i SyncMarker) String() string { i -= 1 diff --git a/vendor/golang.org/x/tools/internal/pkgbits/version.go b/vendor/golang.org/x/tools/internal/pkgbits/version.go new file mode 100644 index 0000000000..53af9df22b --- /dev/null +++ b/vendor/golang.org/x/tools/internal/pkgbits/version.go @@ -0,0 +1,85 @@ +// 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 pkgbits + +// Version indicates a version of a unified IR bitstream. +// Each Version indicates the addition, removal, or change of +// new data in the bitstream. +// +// These are serialized to disk and the interpretation remains fixed. +type Version uint32 + +const ( + // V0: initial prototype. + // + // All data that is not assigned a Field is in version V0 + // and has not been deprecated. + V0 Version = iota + + // V1: adds the Flags uint32 word + V1 + + // V2: removes unused legacy fields and supports type parameters for aliases. + // - remove the legacy "has init" bool from the public root + // - remove obj's "derived func instance" bool + // - add a TypeParamNames field to ObjAlias + // - remove derived info "needed" bool + V2 + + numVersions = iota +) + +// Field denotes a unit of data in the serialized unified IR bitstream. +// It is conceptually a like field in a structure. +// +// We only really need Fields when the data may or may not be present +// in a stream based on the Version of the bitstream. +// +// Unlike much of pkgbits, Fields are not serialized and +// can change values as needed. +type Field int + +const ( + // Flags in a uint32 in the header of a bitstream + // that is used to indicate whether optional features are enabled. + Flags Field = iota + + // Deprecated: HasInit was a bool indicating whether a package + // has any init functions. + HasInit + + // Deprecated: DerivedFuncInstance was a bool indicating + // whether an object was a function instance. + DerivedFuncInstance + + // ObjAlias has a list of TypeParamNames. + AliasTypeParamNames + + // Deprecated: DerivedInfoNeeded was a bool indicating + // whether a type was a derived type. + DerivedInfoNeeded + + numFields = iota +) + +// introduced is the version a field was added. +var introduced = [numFields]Version{ + Flags: V1, + AliasTypeParamNames: V2, +} + +// removed is the version a field was removed in or 0 for fields +// that have not yet been deprecated. +// (So removed[f]-1 is the last version it is included in.) +var removed = [numFields]Version{ + HasInit: V2, + DerivedFuncInstance: V2, + DerivedInfoNeeded: V2, +} + +// Has reports whether field f is present in a bitstream at version v. +func (v Version) Has(f Field) bool { + return introduced[f] <= v && (v < removed[f] || removed[f] == V0) +} diff --git a/vendor/golang.org/x/tools/internal/stdlib/manifest.go b/vendor/golang.org/x/tools/internal/stdlib/manifest.go index a928acf29f..cdaac9ab34 100644 --- a/vendor/golang.org/x/tools/internal/stdlib/manifest.go +++ b/vendor/golang.org/x/tools/internal/stdlib/manifest.go @@ -951,7 +951,7 @@ var PackageSymbols = map[string][]Symbol{ {"ParseSessionState", Func, 21}, {"QUICClient", Func, 21}, {"QUICConfig", Type, 21}, - {"QUICConfig.EnableStoreSessionEvent", Field, 23}, + {"QUICConfig.EnableSessionEvents", Field, 23}, {"QUICConfig.TLSConfig", Field, 21}, {"QUICConn", Type, 21}, {"QUICEncryptionLevel", Type, 21}, diff --git a/vendor/golang.org/x/tools/internal/tokeninternal/tokeninternal.go b/vendor/golang.org/x/tools/internal/tokeninternal/tokeninternal.go deleted file mode 100644 index ff9437a36c..0000000000 --- a/vendor/golang.org/x/tools/internal/tokeninternal/tokeninternal.go +++ /dev/null @@ -1,137 +0,0 @@ -// 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 tokeninternal provides access to some internal features of the token -// package. -package tokeninternal - -import ( - "fmt" - "go/token" - "sort" - "sync" - "unsafe" -) - -// GetLines returns the table of line-start offsets from a token.File. -func GetLines(file *token.File) []int { - // token.File has a Lines method on Go 1.21 and later. - if file, ok := (interface{})(file).(interface{ Lines() []int }); ok { - return file.Lines() - } - - // This declaration must match that of token.File. - // This creates a risk of dependency skew. - // For now we check that the size of the two - // declarations is the same, on the (fragile) assumption - // that future changes would add fields. - type tokenFile119 struct { - _ string - _ int - _ int - mu sync.Mutex // we're not complete monsters - lines []int - _ []struct{} - } - - 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 -// are not already present. It panics if any pair of files in the -// resulting FileSet would overlap. -func AddExistingFiles(fset *token.FileSet, files []*token.File) { - // Punch through the FileSet encapsulation. - type tokenFileSet struct { - // This type remained essentially consistent from go1.16 to go1.21. - mutex sync.RWMutex - base int - files []*token.File - _ *token.File // changed to atomic.Pointer[token.File] in go1.19 - } - - // If the size of token.FileSet changes, this will fail to compile. - const delta = int64(unsafe.Sizeof(tokenFileSet{})) - int64(unsafe.Sizeof(token.FileSet{})) - var _ [-delta * delta]int - - type uP = unsafe.Pointer - var ptr *tokenFileSet - *(*uP)(uP(&ptr)) = uP(fset) - ptr.mutex.Lock() - defer ptr.mutex.Unlock() - - // Merge and sort. - newFiles := append(ptr.files, files...) - sort.Slice(newFiles, func(i, j int) bool { - return newFiles[i].Base() < newFiles[j].Base() - }) - - // Reject overlapping files. - // Discard adjacent identical files. - out := newFiles[:0] - for i, file := range newFiles { - if i > 0 { - prev := newFiles[i-1] - if file == prev { - continue - } - if prev.Base()+prev.Size()+1 > file.Base() { - panic(fmt.Sprintf("file %s (%d-%d) overlaps with file %s (%d-%d)", - prev.Name(), prev.Base(), prev.Base()+prev.Size(), - file.Name(), file.Base(), file.Base()+file.Size())) - } - } - out = append(out, file) - } - newFiles = out - - ptr.files = newFiles - - // Advance FileSet.Base(). - if len(newFiles) > 0 { - last := newFiles[len(newFiles)-1] - newBase := last.Base() + last.Size() + 1 - if ptr.base < newBase { - ptr.base = newBase - } - } -} - -// FileSetFor returns a new FileSet containing a sequence of new Files with -// the same base, size, and line as the input files, for use in APIs that -// require a FileSet. -// -// Precondition: the input files must be non-overlapping, and sorted in order -// of their Base. -func FileSetFor(files ...*token.File) *token.FileSet { - fset := token.NewFileSet() - for _, f := range files { - f2 := fset.AddFile(f.Name(), f.Base(), f.Size()) - lines := GetLines(f) - f2.SetLines(lines) - } - return fset -} - -// CloneFileSet creates a new FileSet holding all files in fset. It does not -// create copies of the token.Files in fset: they are added to the resulting -// FileSet unmodified. -func CloneFileSet(fset *token.FileSet) *token.FileSet { - var files []*token.File - fset.Iterate(func(f *token.File) bool { - files = append(files, f) - return true - }) - newFileSet := token.NewFileSet() - AddExistingFiles(newFileSet, files) - return newFileSet -} diff --git a/vendor/golang.org/x/tools/internal/typeparams/common.go b/vendor/golang.org/x/tools/internal/typeparams/common.go new file mode 100644 index 0000000000..0b84acc5c7 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/typeparams/common.go @@ -0,0 +1,140 @@ +// 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. It +// supplements 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 ( + "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 (or an alias of one). +func IsTypeParam(t types.Type) bool { + _, ok := types.Unalias(t).(*types.TypeParam) + return ok +} + +// 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 instantiation 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 { + V = types.Unalias(V) + T = types.Unalias(T) + + // 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 new file mode 100644 index 0000000000..6e83c6fb1a --- /dev/null +++ b/vendor/golang.org/x/tools/internal/typeparams/coretype.go @@ -0,0 +1,150 @@ +// 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 ( + "fmt" + "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.Underlying().(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 + } +} + +// Deref returns the type of the variable pointed to by t, +// if t's core type is a pointer; otherwise it returns t. +// +// Do not assume that Deref(T)==T implies T is not a pointer: +// consider "type T *T", for example. +// +// TODO(adonovan): ideally this would live in typesinternal, but that +// creates an import cycle. Move there when we melt this package down. +func Deref(t types.Type) types.Type { + if ptr, ok := CoreType(t).(*types.Pointer); ok { + return ptr.Elem() + } + return t +} + +// MustDeref returns the type of the variable pointed to by t. +// It panics if t's core type is not a pointer. +// +// TODO(adonovan): ideally this would live in typesinternal, but that +// creates an import cycle. Move there when we melt this package down. +func MustDeref(t types.Type) types.Type { + if ptr, ok := CoreType(t).(*types.Pointer); ok { + return ptr.Elem() + } + panic(fmt.Sprintf("%v is not a pointer", t)) +} diff --git a/vendor/golang.org/x/tools/internal/typeparams/free.go b/vendor/golang.org/x/tools/internal/typeparams/free.go new file mode 100644 index 0000000000..0ade5c2949 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/typeparams/free.go @@ -0,0 +1,131 @@ +// 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 typeparams + +import ( + "go/types" + + "golang.org/x/tools/internal/aliases" +) + +// Free is a memoization of the set of free type parameters within a +// type. It makes a sequence of calls to [Free.Has] for overlapping +// types more efficient. The zero value is ready for use. +// +// NOTE: Adapted from go/types/infer.go. If it is later exported, factor. +type Free struct { + seen map[types.Type]bool +} + +// Has reports whether the specified type has a free type parameter. +func (w *Free) Has(typ types.Type) (res bool) { + // detect cycles + if x, ok := w.seen[typ]; ok { + return x + } + if w.seen == nil { + w.seen = make(map[types.Type]bool) + } + w.seen[typ] = false + defer func() { + w.seen[typ] = res + }() + + switch t := typ.(type) { + case nil, *types.Basic: // TODO(gri) should nil be handled here? + break + + case *types.Alias: + if aliases.TypeParams(t).Len() > aliases.TypeArgs(t).Len() { + return true // This is an uninstantiated Alias. + } + // The expansion of an alias can have free type parameters, + // whether or not the alias itself has type parameters: + // + // func _[K comparable]() { + // type Set = map[K]bool // free(Set) = {K} + // type MapTo[V] = map[K]V // free(Map[foo]) = {V} + // } + // + // So, we must Unalias. + return w.Has(types.Unalias(t)) + + case *types.Array: + return w.Has(t.Elem()) + + case *types.Slice: + return w.Has(t.Elem()) + + case *types.Struct: + for i, n := 0, t.NumFields(); i < n; i++ { + if w.Has(t.Field(i).Type()) { + return true + } + } + + case *types.Pointer: + return w.Has(t.Elem()) + + case *types.Tuple: + n := t.Len() + for i := 0; i < n; i++ { + if w.Has(t.At(i).Type()) { + return true + } + } + + case *types.Signature: + // t.tparams may not be nil if we are looking at a signature + // of a generic function type (or an interface method) that is + // part of the type we're testing. We don't care about these type + // parameters. + // Similarly, the receiver of a method may declare (rather than + // use) type parameters, we don't care about those either. + // Thus, we only need to look at the input and result parameters. + return w.Has(t.Params()) || w.Has(t.Results()) + + case *types.Interface: + for i, n := 0, t.NumMethods(); i < n; i++ { + if w.Has(t.Method(i).Type()) { + return true + } + } + terms, err := InterfaceTermSet(t) + if err != nil { + return false // ill typed + } + for _, term := range terms { + if w.Has(term.Type()) { + return true + } + } + + case *types.Map: + return w.Has(t.Key()) || w.Has(t.Elem()) + + case *types.Chan: + return w.Has(t.Elem()) + + case *types.Named: + args := t.TypeArgs() + if params := t.TypeParams(); params.Len() > args.Len() { + return true // this is an uninstantiated named type. + } + for i, n := 0, args.Len(); i < n; i++ { + if w.Has(args.At(i)) { + return true + } + } + return w.Has(t.Underlying()) // recurse for types local to parameterized functions + + case *types.TypeParam: + return true + + default: + panic(t) // unreachable + } + + return false +} diff --git a/vendor/golang.org/x/tools/internal/typeparams/normalize.go b/vendor/golang.org/x/tools/internal/typeparams/normalize.go new file mode 100644 index 0000000000..93c80fdc96 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/typeparams/normalize.go @@ -0,0 +1,218 @@ +// 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 new file mode 100644 index 0000000000..cbd12f8013 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/typeparams/termlist.go @@ -0,0 +1,163 @@ +// 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 new file mode 100644 index 0000000000..7350bb702a --- /dev/null +++ b/vendor/golang.org/x/tools/internal/typeparams/typeterm.go @@ -0,0 +1,169 @@ +// 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/element.go b/vendor/golang.org/x/tools/internal/typesinternal/element.go new file mode 100644 index 0000000000..4957f02164 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/typesinternal/element.go @@ -0,0 +1,133 @@ +// 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 ( + "fmt" + "go/types" + + "golang.org/x/tools/go/types/typeutil" +) + +// ForEachElement calls f for type T and each type reachable from its +// type through reflection. It does this by recursively stripping off +// type constructors; in addition, for each named type N, the type *N +// is added to the result as it may have additional methods. +// +// The caller must provide an initially empty set used to de-duplicate +// identical types, potentially across multiple calls to ForEachElement. +// (Its final value holds all the elements seen, matching the arguments +// passed to f.) +// +// TODO(adonovan): share/harmonize with go/callgraph/rta. +func ForEachElement(rtypes *typeutil.Map, msets *typeutil.MethodSetCache, T types.Type, f func(types.Type)) { + var visit func(T types.Type, skip bool) + visit = func(T types.Type, skip bool) { + if !skip { + if seen, _ := rtypes.Set(T, true).(bool); seen { + return // de-dup + } + + f(T) // notify caller of new element type + } + + // Recursion over signatures of each method. + tmset := msets.MethodSet(T) + for i := 0; i < tmset.Len(); i++ { + sig := tmset.At(i).Type().(*types.Signature) + // It is tempting to call visit(sig, false) + // but, as noted in golang.org/cl/65450043, + // the Signature.Recv field is ignored by + // types.Identical and typeutil.Map, which + // is confusing at best. + // + // More importantly, the true signature rtype + // reachable from a method using reflection + // has no receiver but an extra ordinary parameter. + // For the Read method of io.Reader we want: + // func(Reader, []byte) (int, error) + // but here sig is: + // func([]byte) (int, error) + // with .Recv = Reader (though it is hard to + // notice because it doesn't affect Signature.String + // or types.Identical). + // + // TODO(adonovan): construct and visit the correct + // non-method signature with an extra parameter + // (though since unnamed func types have no methods + // there is essentially no actual demand for this). + // + // TODO(adonovan): document whether or not it is + // safe to skip non-exported methods (as RTA does). + visit(sig.Params(), true) // skip the Tuple + visit(sig.Results(), true) // skip the Tuple + } + + switch T := T.(type) { + case *types.Alias: + visit(types.Unalias(T), skip) // emulates the pre-Alias behavior + + case *types.Basic: + // nop + + case *types.Interface: + // nop---handled by recursion over method set. + + case *types.Pointer: + visit(T.Elem(), false) + + case *types.Slice: + visit(T.Elem(), false) + + case *types.Chan: + visit(T.Elem(), false) + + case *types.Map: + visit(T.Key(), false) + visit(T.Elem(), false) + + case *types.Signature: + if T.Recv() != nil { + panic(fmt.Sprintf("Signature %s has Recv %s", T, T.Recv())) + } + visit(T.Params(), true) // skip the Tuple + visit(T.Results(), true) // skip the Tuple + + case *types.Named: + // A pointer-to-named type can be derived from a named + // type via reflection. It may have methods too. + visit(types.NewPointer(T), false) + + // Consider 'type T struct{S}' where S has methods. + // Reflection provides no way to get from T to struct{S}, + // only to S, so the method set of struct{S} is unwanted, + // so set 'skip' flag during recursion. + visit(T.Underlying(), true) // skip the unnamed type + + case *types.Array: + visit(T.Elem(), false) + + case *types.Struct: + for i, n := 0, T.NumFields(); i < n; i++ { + // TODO(adonovan): document whether or not + // it is safe to skip non-exported fields. + visit(T.Field(i).Type(), false) + } + + case *types.Tuple: + for i, n := 0, T.Len(); i < n; i++ { + visit(T.At(i).Type(), false) + } + + case *types.TypeParam, *types.Union: + // forEachReachable must not be called on parameterized types. + panic(T) + + default: + panic(T) + } + } + visit(T, false) +} diff --git a/vendor/golang.org/x/tools/internal/typesinternal/errorcode.go b/vendor/golang.org/x/tools/internal/typesinternal/errorcode.go index 834e05381c..131caab284 100644 --- a/vendor/golang.org/x/tools/internal/typesinternal/errorcode.go +++ b/vendor/golang.org/x/tools/internal/typesinternal/errorcode.go @@ -838,7 +838,7 @@ const ( // InvalidCap occurs when an argument to the cap built-in function is not of // supported type. // - // See https://golang.org/ref/spec#Lengthand_capacity for information on + // See https://golang.org/ref/spec#Length_and_capacity for information on // which underlying types are supported as arguments to cap and len. // // Example: @@ -859,7 +859,7 @@ const ( // InvalidCopy occurs when the arguments are not of slice type or do not // have compatible type. // - // See https://golang.org/ref/spec#Appendingand_copying_slices for more + // See https://golang.org/ref/spec#Appending_and_copying_slices for more // information on the type requirements for the copy built-in. // // Example: @@ -897,7 +897,7 @@ const ( // InvalidLen occurs when an argument to the len built-in function is not of // supported type. // - // See https://golang.org/ref/spec#Lengthand_capacity for information on + // See https://golang.org/ref/spec#Length_and_capacity for information on // which underlying types are supported as arguments to cap and len. // // Example: @@ -914,7 +914,7 @@ const ( // InvalidMake occurs when make is called with an unsupported type argument. // - // See https://golang.org/ref/spec#Makingslices_maps_and_channels for + // See https://golang.org/ref/spec#Making_slices_maps_and_channels for // information on the types that may be created using make. // // Example: diff --git a/vendor/golang.org/x/tools/internal/typesinternal/recv.go b/vendor/golang.org/x/tools/internal/typesinternal/recv.go index fea7c8b75e..ba6f4f4ebd 100644 --- a/vendor/golang.org/x/tools/internal/typesinternal/recv.go +++ b/vendor/golang.org/x/tools/internal/typesinternal/recv.go @@ -6,8 +6,6 @@ package typesinternal import ( "go/types" - - "golang.org/x/tools/internal/aliases" ) // ReceiverNamed returns the named type (if any) associated with the @@ -15,11 +13,11 @@ import ( // 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 { + if ptr, ok := types.Unalias(t).(*types.Pointer); ok { isPtr = true t = ptr.Elem() } - named, _ = aliases.Unalias(t).(*types.Named) + named, _ = types.Unalias(t).(*types.Named) return } @@ -36,7 +34,7 @@ func ReceiverNamed(recv *types.Var) (isPtr bool, named *types.Named) { // 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 { + if ptr, ok := types.Unalias(t).(*types.Pointer); ok { return ptr.Elem() } return t diff --git a/vendor/golang.org/x/tools/internal/typesinternal/types.go b/vendor/golang.org/x/tools/internal/typesinternal/types.go index 8392328612..df3ea52125 100644 --- a/vendor/golang.org/x/tools/internal/typesinternal/types.go +++ b/vendor/golang.org/x/tools/internal/typesinternal/types.go @@ -11,6 +11,8 @@ import ( "go/types" "reflect" "unsafe" + + "golang.org/x/tools/internal/aliases" ) func SetUsesCgo(conf *types.Config) bool { @@ -63,3 +65,57 @@ func NameRelativeTo(pkg *types.Package) types.Qualifier { return other.Name() } } + +// A NamedOrAlias is a [types.Type] that is named (as +// defined by the spec) and capable of bearing type parameters: it +// abstracts aliases ([types.Alias]) and defined types +// ([types.Named]). +// +// Every type declared by an explicit "type" declaration is a +// NamedOrAlias. (Built-in type symbols may additionally +// have type [types.Basic], which is not a NamedOrAlias, +// though the spec regards them as "named".) +// +// NamedOrAlias cannot expose the Origin method, because +// [types.Alias.Origin] and [types.Named.Origin] have different +// (covariant) result types; use [Origin] instead. +type NamedOrAlias interface { + types.Type + Obj() *types.TypeName +} + +// TypeParams is a light shim around t.TypeParams(). +// (go/types.Alias).TypeParams requires >= 1.23. +func TypeParams(t NamedOrAlias) *types.TypeParamList { + switch t := t.(type) { + case *types.Alias: + return aliases.TypeParams(t) + case *types.Named: + return t.TypeParams() + } + return nil +} + +// TypeArgs is a light shim around t.TypeArgs(). +// (go/types.Alias).TypeArgs requires >= 1.23. +func TypeArgs(t NamedOrAlias) *types.TypeList { + switch t := t.(type) { + case *types.Alias: + return aliases.TypeArgs(t) + case *types.Named: + return t.TypeArgs() + } + return nil +} + +// Origin returns the generic type of the Named or Alias type t if it +// is instantiated, otherwise it returns t. +func Origin(t NamedOrAlias) NamedOrAlias { + switch t := t.(type) { + case *types.Alias: + return aliases.Origin(t) + case *types.Named: + return t.Origin() + } + return t +} diff --git a/vendor/golang.org/x/tools/internal/typesinternal/zerovalue.go b/vendor/golang.org/x/tools/internal/typesinternal/zerovalue.go new file mode 100644 index 0000000000..1066980649 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/typesinternal/zerovalue.go @@ -0,0 +1,282 @@ +// 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 ( + "fmt" + "go/ast" + "go/token" + "go/types" + "strconv" + "strings" +) + +// ZeroString returns the string representation of the "zero" value of the type t. +// This string can be used on the right-hand side of an assignment where the +// left-hand side has that explicit type. +// Exception: This does not apply to tuples. Their string representation is +// informational only and cannot be used in an assignment. +// When assigning to a wider type (such as 'any'), it's the caller's +// responsibility to handle any necessary type conversions. +// See [ZeroExpr] for a variant that returns an [ast.Expr]. +func ZeroString(t types.Type, qf types.Qualifier) string { + switch t := t.(type) { + case *types.Basic: + switch { + case t.Info()&types.IsBoolean != 0: + return "false" + case t.Info()&types.IsNumeric != 0: + return "0" + case t.Info()&types.IsString != 0: + return `""` + case t.Kind() == types.UnsafePointer: + fallthrough + case t.Kind() == types.UntypedNil: + return "nil" + default: + panic(fmt.Sprint("ZeroString for unexpected type:", t)) + } + + case *types.Pointer, *types.Slice, *types.Interface, *types.Chan, *types.Map, *types.Signature: + return "nil" + + case *types.Named, *types.Alias: + switch under := t.Underlying().(type) { + case *types.Struct, *types.Array: + return types.TypeString(t, qf) + "{}" + default: + return ZeroString(under, qf) + } + + case *types.Array, *types.Struct: + return types.TypeString(t, qf) + "{}" + + case *types.TypeParam: + // Assumes func new is not shadowed. + return "*new(" + types.TypeString(t, qf) + ")" + + case *types.Tuple: + // Tuples are not normal values. + // We are currently format as "(t[0], ..., t[n])". Could be something else. + components := make([]string, t.Len()) + for i := 0; i < t.Len(); i++ { + components[i] = ZeroString(t.At(i).Type(), qf) + } + return "(" + strings.Join(components, ", ") + ")" + + case *types.Union: + // Variables of these types cannot be created, so it makes + // no sense to ask for their zero value. + panic(fmt.Sprintf("invalid type for a variable: %v", t)) + + default: + panic(t) // unreachable. + } +} + +// ZeroExpr returns the ast.Expr representation of the "zero" value of the type t. +// ZeroExpr is defined for types that are suitable for variables. +// It may panic for other types such as Tuple or Union. +// See [ZeroString] for a variant that returns a string. +func ZeroExpr(f *ast.File, pkg *types.Package, typ types.Type) ast.Expr { + switch t := typ.(type) { + case *types.Basic: + switch { + case t.Info()&types.IsBoolean != 0: + return &ast.Ident{Name: "false"} + case t.Info()&types.IsNumeric != 0: + return &ast.BasicLit{Kind: token.INT, Value: "0"} + case t.Info()&types.IsString != 0: + return &ast.BasicLit{Kind: token.STRING, Value: `""`} + case t.Kind() == types.UnsafePointer: + fallthrough + case t.Kind() == types.UntypedNil: + return ast.NewIdent("nil") + default: + panic(fmt.Sprint("ZeroExpr for unexpected type:", t)) + } + + case *types.Pointer, *types.Slice, *types.Interface, *types.Chan, *types.Map, *types.Signature: + return ast.NewIdent("nil") + + case *types.Named, *types.Alias: + switch under := t.Underlying().(type) { + case *types.Struct, *types.Array: + return &ast.CompositeLit{ + Type: TypeExpr(f, pkg, typ), + } + default: + return ZeroExpr(f, pkg, under) + } + + case *types.Array, *types.Struct: + return &ast.CompositeLit{ + Type: TypeExpr(f, pkg, typ), + } + + case *types.TypeParam: + return &ast.StarExpr{ // *new(T) + X: &ast.CallExpr{ + // Assumes func new is not shadowed. + Fun: ast.NewIdent("new"), + Args: []ast.Expr{ + ast.NewIdent(t.Obj().Name()), + }, + }, + } + + case *types.Tuple: + // Unlike ZeroString, there is no ast.Expr can express tuple by + // "(t[0], ..., t[n])". + panic(fmt.Sprintf("invalid type for a variable: %v", t)) + + case *types.Union: + // Variables of these types cannot be created, so it makes + // no sense to ask for their zero value. + panic(fmt.Sprintf("invalid type for a variable: %v", t)) + + default: + panic(t) // unreachable. + } +} + +// IsZeroExpr uses simple syntactic heuristics to report whether expr +// is a obvious zero value, such as 0, "", nil, or false. +// It cannot do better without type information. +func IsZeroExpr(expr ast.Expr) bool { + switch e := expr.(type) { + case *ast.BasicLit: + return e.Value == "0" || e.Value == `""` + case *ast.Ident: + return e.Name == "nil" || e.Name == "false" + default: + return false + } +} + +// TypeExpr returns syntax for the specified type. References to named types +// from packages other than pkg are qualified by an appropriate package name, as +// defined by the import environment of file. +// It may panic for types such as Tuple or Union. +func TypeExpr(f *ast.File, pkg *types.Package, typ types.Type) ast.Expr { + switch t := typ.(type) { + case *types.Basic: + switch t.Kind() { + case types.UnsafePointer: + // TODO(hxjiang): replace the implementation with types.Qualifier. + return &ast.SelectorExpr{X: ast.NewIdent("unsafe"), Sel: ast.NewIdent("Pointer")} + default: + return ast.NewIdent(t.Name()) + } + + case *types.Pointer: + return &ast.UnaryExpr{ + Op: token.MUL, + X: TypeExpr(f, pkg, t.Elem()), + } + + case *types.Array: + return &ast.ArrayType{ + Len: &ast.BasicLit{ + Kind: token.INT, + Value: fmt.Sprintf("%d", t.Len()), + }, + Elt: TypeExpr(f, pkg, t.Elem()), + } + + case *types.Slice: + return &ast.ArrayType{ + Elt: TypeExpr(f, pkg, t.Elem()), + } + + case *types.Map: + return &ast.MapType{ + Key: TypeExpr(f, pkg, t.Key()), + Value: TypeExpr(f, pkg, t.Elem()), + } + + case *types.Chan: + dir := ast.ChanDir(t.Dir()) + if t.Dir() == types.SendRecv { + dir = ast.SEND | ast.RECV + } + return &ast.ChanType{ + Dir: dir, + Value: TypeExpr(f, pkg, t.Elem()), + } + + case *types.Signature: + var params []*ast.Field + for i := 0; i < t.Params().Len(); i++ { + params = append(params, &ast.Field{ + Type: TypeExpr(f, pkg, t.Params().At(i).Type()), + Names: []*ast.Ident{ + { + Name: t.Params().At(i).Name(), + }, + }, + }) + } + if t.Variadic() { + last := params[len(params)-1] + last.Type = &ast.Ellipsis{Elt: last.Type.(*ast.ArrayType).Elt} + } + var returns []*ast.Field + for i := 0; i < t.Results().Len(); i++ { + returns = append(returns, &ast.Field{ + Type: TypeExpr(f, pkg, t.Results().At(i).Type()), + }) + } + return &ast.FuncType{ + Params: &ast.FieldList{ + List: params, + }, + Results: &ast.FieldList{ + List: returns, + }, + } + + case interface{ Obj() *types.TypeName }: // *types.{Alias,Named,TypeParam} + switch t.Obj().Pkg() { + case pkg, nil: + return ast.NewIdent(t.Obj().Name()) + } + pkgName := t.Obj().Pkg().Name() + + // TODO(hxjiang): replace the implementation with types.Qualifier. + // If the file already imports the package under another name, use that. + for _, cand := range f.Imports { + if path, _ := strconv.Unquote(cand.Path.Value); path == t.Obj().Pkg().Path() { + if cand.Name != nil && cand.Name.Name != "" { + pkgName = cand.Name.Name + } + } + } + if pkgName == "." { + return ast.NewIdent(t.Obj().Name()) + } + return &ast.SelectorExpr{ + X: ast.NewIdent(pkgName), + Sel: ast.NewIdent(t.Obj().Name()), + } + + case *types.Struct: + return ast.NewIdent(t.String()) + + case *types.Interface: + return ast.NewIdent(t.String()) + + case *types.Union: + // TODO(hxjiang): handle the union through syntax (~A | ... | ~Z). + // Remove nil check when calling typesinternal.TypeExpr. + return nil + + case *types.Tuple: + panic("invalid input type types.Tuple") + + default: + panic("unreachable") + } +} diff --git a/vendor/golang.org/x/tools/internal/versions/constraint.go b/vendor/golang.org/x/tools/internal/versions/constraint.go deleted file mode 100644 index 179063d484..0000000000 --- a/vendor/golang.org/x/tools/internal/versions/constraint.go +++ /dev/null @@ -1,13 +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 versions - -import "go/build/constraint" - -// ConstraintGoVersion is constraint.GoVersion (if built with go1.21+). -// Otherwise nil. -// -// Deprecate once x/tools is after go1.21. -var ConstraintGoVersion func(x constraint.Expr) string diff --git a/vendor/golang.org/x/tools/internal/versions/constraint_go121.go b/vendor/golang.org/x/tools/internal/versions/constraint_go121.go deleted file mode 100644 index 38011407d5..0000000000 --- a/vendor/golang.org/x/tools/internal/versions/constraint_go121.go +++ /dev/null @@ -1,14 +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. - -//go:build go1.21 -// +build go1.21 - -package versions - -import "go/build/constraint" - -func init() { - ConstraintGoVersion = constraint.GoVersion -} diff --git a/vendor/golang.org/x/tools/internal/versions/toolchain.go b/vendor/golang.org/x/tools/internal/versions/toolchain.go deleted file mode 100644 index 377bf7a53b..0000000000 --- a/vendor/golang.org/x/tools/internal/versions/toolchain.go +++ /dev/null @@ -1,14 +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 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 deleted file mode 100644 index f65beed9d8..0000000000 --- a/vendor/golang.org/x/tools/internal/versions/toolchain_go119.go +++ /dev/null @@ -1,14 +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. - -//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 deleted file mode 100644 index 1a9efa126c..0000000000 --- a/vendor/golang.org/x/tools/internal/versions/toolchain_go120.go +++ /dev/null @@ -1,14 +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. - -//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 deleted file mode 100644 index b7ef216dfe..0000000000 --- a/vendor/golang.org/x/tools/internal/versions/toolchain_go121.go +++ /dev/null @@ -1,14 +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. - -//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.go b/vendor/golang.org/x/tools/internal/versions/types.go index 562eef21fa..0fc10ce4eb 100644 --- a/vendor/golang.org/x/tools/internal/versions/types.go +++ b/vendor/golang.org/x/tools/internal/versions/types.go @@ -5,15 +5,29 @@ package versions import ( + "go/ast" "go/types" ) -// GoVersion returns the Go version of the type package. -// It returns zero if no version can be determined. -func GoVersion(pkg *types.Package) string { - // TODO(taking): x/tools can call GoVersion() [from 1.21] after 1.25. - if pkg, ok := any(pkg).(interface{ GoVersion() string }); ok { - return pkg.GoVersion() +// 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 } - return "" + // Note: we could instead return runtime.Version() [if valid]. + // This would act as a max version on what a tool can support. + return Future } diff --git a/vendor/golang.org/x/tools/internal/versions/types_go121.go b/vendor/golang.org/x/tools/internal/versions/types_go121.go deleted file mode 100644 index b4345d3349..0000000000 --- a/vendor/golang.org/x/tools/internal/versions/types_go121.go +++ /dev/null @@ -1,30 +0,0 @@ -// 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.22 -// +build !go1.22 - -package versions - -import ( - "go/ast" - "go/types" -) - -// 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 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 deleted file mode 100644 index aac5db62c9..0000000000 --- a/vendor/golang.org/x/tools/internal/versions/types_go122.go +++ /dev/null @@ -1,41 +0,0 @@ -// 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.22 -// +build go1.22 - -package versions - -import ( - "go/ast" - "go/types" -) - -// 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. -func InitFileVersions(info *types.Info) { - info.FileVersions = make(map[*ast.File]string) -} diff --git a/vendor/google.golang.org/genproto/googleapis/rpc/errdetails/error_details.pb.go b/vendor/google.golang.org/genproto/googleapis/rpc/errdetails/error_details.pb.go index 3e56218279..3cd9a5bb8e 100644 --- a/vendor/google.golang.org/genproto/googleapis/rpc/errdetails/error_details.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/rpc/errdetails/error_details.pb.go @@ -80,11 +80,12 @@ type ErrorInfo struct { Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"` // Additional structured details about this error. // - // Keys should match /[a-zA-Z0-9-_]/ and be limited to 64 characters in + // Keys must match a regular expression of `[a-z][a-zA-Z0-9-_]+` but should + // ideally be lowerCamelCase. Also, they must be limited to 64 characters in // length. When identifying the current value of an exceeded limit, the units // should be contained in the key, not the value. For example, rather than - // {"instanceLimit": "100/request"}, should be returned as, - // {"instanceLimitPerRequest": "100"}, if the client exceeds the number of + // `{"instanceLimit": "100/request"}`, should be returned as, + // `{"instanceLimitPerRequest": "100"}`, if the client exceeds the number of // instances that can be created in a single (batch) request. Metadata map[string]string `protobuf:"bytes,3,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } @@ -870,6 +871,16 @@ type BadRequest_FieldViolation struct { Field string `protobuf:"bytes,1,opt,name=field,proto3" json:"field,omitempty"` // A description of why the request element is bad. Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + // The reason of the field-level error. This is a constant value that + // identifies the proximate cause of the field-level error. It should + // uniquely identify the type of the FieldViolation within the scope of the + // google.rpc.ErrorInfo.domain. This should be at most 63 + // characters and match a regular expression of `[A-Z][A-Z0-9_]+[A-Z0-9]`, + // which represents UPPER_SNAKE_CASE. + Reason string `protobuf:"bytes,3,opt,name=reason,proto3" json:"reason,omitempty"` + // Provides a localized error message for field-level errors that is safe to + // return to the API consumer. + LocalizedMessage *LocalizedMessage `protobuf:"bytes,4,opt,name=localized_message,json=localizedMessage,proto3" json:"localized_message,omitempty"` } func (x *BadRequest_FieldViolation) Reset() { @@ -918,6 +929,20 @@ func (x *BadRequest_FieldViolation) GetDescription() string { return "" } +func (x *BadRequest_FieldViolation) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +func (x *BadRequest_FieldViolation) GetLocalizedMessage() *LocalizedMessage { + if x != nil { + return x.LocalizedMessage + } + return nil +} + // Describes a URL link. type Help_Link struct { state protoimpl.MessageState @@ -1026,51 +1051,57 @@ var file_google_rpc_error_details_proto_rawDesc = []byte{ 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xa8, 0x01, 0x0a, 0x0a, 0x42, 0x61, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x8c, 0x02, 0x0a, 0x0a, 0x42, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x50, 0x0a, 0x10, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x48, 0x0a, 0x0e, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, - 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x4f, 0x0a, 0x0b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, - 0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x61, - 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, - 0x67, 0x44, 0x61, 0x74, 0x61, 0x22, 0x90, 0x01, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, - 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x6f, 0x0a, 0x04, 0x48, 0x65, 0x6c, 0x70, - 0x12, 0x2b, 0x0a, 0x05, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x15, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x48, 0x65, 0x6c, - 0x70, 0x2e, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x1a, 0x3a, 0x0a, - 0x04, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x44, 0x0a, 0x10, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, - 0x06, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, - 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, - 0x6c, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, - 0x63, 0x42, 0x11, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3f, 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, 0x72, 0x70, - 0x63, 0x2f, 0x65, 0x72, 0x72, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x3b, 0x65, 0x72, 0x72, - 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0xa2, 0x02, 0x03, 0x52, 0x50, 0x43, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0xab, 0x01, 0x0a, 0x0e, 0x46, + 0x69, 0x65, 0x6c, 0x64, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, + 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x66, 0x69, + 0x65, 0x6c, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x49, 0x0a, + 0x11, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x10, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, + 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x4f, 0x0a, 0x0b, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, + 0x67, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x6e, 0x67, 0x44, 0x61, 0x74, 0x61, 0x22, 0x90, 0x01, 0x0a, 0x0c, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x6f, 0x0a, 0x04, + 0x48, 0x65, 0x6c, 0x70, 0x12, 0x2b, 0x0a, 0x05, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, + 0x2e, 0x48, 0x65, 0x6c, 0x70, 0x2e, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x6b, + 0x73, 0x1a, 0x3a, 0x0a, 0x04, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x75, + 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x44, 0x0a, + 0x10, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x42, 0x6c, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x72, 0x70, 0x63, 0x42, 0x11, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x44, 0x65, 0x74, 0x61, + 0x69, 0x6c, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3f, 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, 0x72, 0x70, 0x63, 0x2f, 0x65, 0x72, 0x72, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, + 0x3b, 0x65, 0x72, 0x72, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0xa2, 0x02, 0x03, 0x52, 0x50, + 0x43, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1111,11 +1142,12 @@ var file_google_rpc_error_details_proto_depIdxs = []int32{ 12, // 3: google.rpc.PreconditionFailure.violations:type_name -> google.rpc.PreconditionFailure.Violation 13, // 4: google.rpc.BadRequest.field_violations:type_name -> google.rpc.BadRequest.FieldViolation 14, // 5: google.rpc.Help.links:type_name -> google.rpc.Help.Link - 6, // [6:6] is the sub-list for method output_type - 6, // [6:6] is the sub-list for method input_type - 6, // [6:6] is the sub-list for extension type_name - 6, // [6:6] is the sub-list for extension extendee - 0, // [0:6] is the sub-list for field type_name + 9, // 6: google.rpc.BadRequest.FieldViolation.localized_message:type_name -> google.rpc.LocalizedMessage + 7, // [7:7] is the sub-list for method output_type + 7, // [7:7] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name } func init() { file_google_rpc_error_details_proto_init() } diff --git a/vendor/google.golang.org/protobuf/encoding/protojson/decode.go b/vendor/google.golang.org/protobuf/encoding/protojson/decode.go index 8f9e592f87..cffdfda961 100644 --- a/vendor/google.golang.org/protobuf/encoding/protojson/decode.go +++ b/vendor/google.golang.org/protobuf/encoding/protojson/decode.go @@ -192,7 +192,7 @@ func (d decoder) unmarshalMessage(m protoreflect.Message, skipTypeURL bool) erro fd = fieldDescs.ByTextName(name) } } - if flags.ProtoLegacy { + if flags.ProtoLegacyWeak { if fd != nil && fd.IsWeak() && fd.Message().IsPlaceholder() { fd = nil // reset since the weak reference is not linked in } diff --git a/vendor/google.golang.org/protobuf/encoding/prototext/decode.go b/vendor/google.golang.org/protobuf/encoding/prototext/decode.go index 24bc98ac42..d972a3d98e 100644 --- a/vendor/google.golang.org/protobuf/encoding/prototext/decode.go +++ b/vendor/google.golang.org/protobuf/encoding/prototext/decode.go @@ -185,7 +185,7 @@ func (d decoder) unmarshalMessage(m protoreflect.Message, checkDelims bool) erro } else if xtErr != nil && xtErr != protoregistry.NotFound { return d.newError(tok.Pos(), "unable to resolve [%s]: %v", tok.RawString(), xtErr) } - if flags.ProtoLegacy { + if flags.ProtoLegacyWeak { if fd != nil && fd.IsWeak() && fd.Message().IsPlaceholder() { fd = nil // reset since the weak reference is not linked in } diff --git a/vendor/google.golang.org/protobuf/internal/flags/flags.go b/vendor/google.golang.org/protobuf/internal/flags/flags.go index 58372dd348..5cb3ee70f9 100644 --- a/vendor/google.golang.org/protobuf/internal/flags/flags.go +++ b/vendor/google.golang.org/protobuf/internal/flags/flags.go @@ -22,3 +22,8 @@ const ProtoLegacy = protoLegacy // extension fields at unmarshal time, but defers creating the message // structure until the extension is first accessed. const LazyUnmarshalExtensions = ProtoLegacy + +// ProtoLegacyWeak specifies whether to enable support for weak fields. +// This flag was split out of ProtoLegacy in preparation for removing +// support for weak fields (independent of the other protolegacy features). +const ProtoLegacyWeak = ProtoLegacy 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 fb35f0bae9..229c698013 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/codec_map.go +++ b/vendor/google.golang.org/protobuf/internal/impl/codec_map.go @@ -94,7 +94,7 @@ func sizeMap(mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalO return 0 } n := 0 - iter := mapRange(mapv) + iter := mapv.MapRange() for iter.Next() { key := mapi.conv.keyConv.PBValueOf(iter.Key()).MapKey() keySize := mapi.keyFuncs.size(key.Value(), mapKeyTagSize, opts) @@ -281,7 +281,7 @@ func appendMap(b []byte, mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo, o if opts.Deterministic() { return appendMapDeterministic(b, mapv, mapi, f, opts) } - iter := mapRange(mapv) + iter := mapv.MapRange() for iter.Next() { var err error b = protowire.AppendVarint(b, f.wiretag) @@ -328,7 +328,7 @@ func isInitMap(mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo) error { if !mi.needsInitCheck { return nil } - iter := mapRange(mapv) + iter := mapv.MapRange() for iter.Next() { val := pointerOfValue(iter.Value()) if err := mi.checkInitializedPointer(val); err != nil { @@ -336,7 +336,7 @@ func isInitMap(mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo) error { } } } else { - iter := mapRange(mapv) + iter := mapv.MapRange() for iter.Next() { val := mapi.conv.valConv.PBValueOf(iter.Value()) if err := mapi.valFuncs.isInit(val); err != nil { @@ -356,7 +356,7 @@ func mergeMap(dst, src pointer, f *coderFieldInfo, opts mergeOptions) { if dstm.IsNil() { dstm.Set(reflect.MakeMap(f.ft)) } - iter := mapRange(srcm) + iter := srcm.MapRange() for iter.Next() { dstm.SetMapIndex(iter.Key(), iter.Value()) } @@ -371,7 +371,7 @@ func mergeMapOfBytes(dst, src pointer, f *coderFieldInfo, opts mergeOptions) { if dstm.IsNil() { dstm.Set(reflect.MakeMap(f.ft)) } - iter := mapRange(srcm) + iter := srcm.MapRange() for iter.Next() { dstm.SetMapIndex(iter.Key(), reflect.ValueOf(append(emptyBuf[:], iter.Value().Bytes()...))) } @@ -386,7 +386,7 @@ func mergeMapOfMessage(dst, src pointer, f *coderFieldInfo, opts mergeOptions) { if dstm.IsNil() { dstm.Set(reflect.MakeMap(f.ft)) } - iter := mapRange(srcm) + iter := srcm.MapRange() for iter.Next() { val := reflect.New(f.ft.Elem().Elem()) if f.mi != nil { diff --git a/vendor/google.golang.org/protobuf/internal/impl/codec_map_go111.go b/vendor/google.golang.org/protobuf/internal/impl/codec_map_go111.go deleted file mode 100644 index 4b15493f2f..0000000000 --- a/vendor/google.golang.org/protobuf/internal/impl/codec_map_go111.go +++ /dev/null @@ -1,38 +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 -// +build !go1.12 - -package impl - -import "reflect" - -type mapIter struct { - v reflect.Value - keys []reflect.Value -} - -// mapRange provides a less-efficient equivalent to -// the Go 1.12 reflect.Value.MapRange method. -func mapRange(v reflect.Value) *mapIter { - return &mapIter{v: v} -} - -func (i *mapIter) Next() bool { - if i.keys == nil { - i.keys = i.v.MapKeys() - } else { - i.keys = i.keys[1:] - } - return len(i.keys) > 0 -} - -func (i *mapIter) Key() reflect.Value { - return i.keys[0] -} - -func (i *mapIter) Value() reflect.Value { - return i.v.MapIndex(i.keys[0]) -} diff --git a/vendor/google.golang.org/protobuf/internal/impl/codec_map_go112.go b/vendor/google.golang.org/protobuf/internal/impl/codec_map_go112.go deleted file mode 100644 index 0b31b66eaf..0000000000 --- a/vendor/google.golang.org/protobuf/internal/impl/codec_map_go112.go +++ /dev/null @@ -1,12 +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 -// +build go1.12 - -package impl - -import "reflect" - -func mapRange(v reflect.Value) *reflect.MapIter { return v.MapRange() } 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 2f7b363ec4..111d95833d 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/codec_message.go +++ b/vendor/google.golang.org/protobuf/internal/impl/codec_message.go @@ -118,12 +118,12 @@ func (mi *MessageInfo) makeCoderMethods(t reflect.Type, si structInfo) { }, } case isOneof: - fieldOffset = offsetOf(fs, mi.Exporter) + fieldOffset = offsetOf(fs) case fd.IsWeak(): fieldOffset = si.weakOffset funcs = makeWeakMessageFieldCoder(fd) default: - fieldOffset = offsetOf(fs, mi.Exporter) + fieldOffset = offsetOf(fs) childMessage, funcs = fieldCoder(fd, ft) } cf := &preallocFields[i] diff --git a/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go b/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go index 88c16ae5b7..f81d7d0db9 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go +++ b/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go @@ -45,19 +45,19 @@ func (mi *MessageInfo) makeOpaqueCoderMethods(t reflect.Type, si opaqueStructInf var childMessage *MessageInfo switch { case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic(): - fieldOffset = offsetOf(fs, mi.Exporter) + fieldOffset = offsetOf(fs) case fd.IsWeak(): fieldOffset = si.weakOffset funcs = makeWeakMessageFieldCoder(fd) case fd.Message() != nil && !fd.IsMap(): - fieldOffset = offsetOf(fs, mi.Exporter) + fieldOffset = offsetOf(fs) if fd.IsList() { childMessage, funcs = makeOpaqueRepeatedMessageFieldCoder(fd, ft) } else { childMessage, funcs = makeOpaqueMessageFieldCoder(fd, ft) } default: - fieldOffset = offsetOf(fs, mi.Exporter) + fieldOffset = offsetOf(fs) childMessage, funcs = fieldCoder(fd, ft) } cf := &coderFieldInfo{ 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 304244a651..e4580b3ac2 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/convert_map.go +++ b/vendor/google.golang.org/protobuf/internal/impl/convert_map.go @@ -101,7 +101,7 @@ func (ms *mapReflect) Mutable(k protoreflect.MapKey) protoreflect.Value { return v } func (ms *mapReflect) Range(f func(protoreflect.MapKey, protoreflect.Value) bool) { - iter := mapRange(ms.v) + iter := ms.v.MapRange() for iter.Next() { k := ms.keyConv.PBValueOf(iter.Key()).MapKey() v := ms.valConv.PBValueOf(iter.Value()) diff --git a/vendor/google.golang.org/protobuf/internal/impl/message.go b/vendor/google.golang.org/protobuf/internal/impl/message.go index fa10a0f5cc..d1f79b4224 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/message.go +++ b/vendor/google.golang.org/protobuf/internal/impl/message.go @@ -165,28 +165,28 @@ fieldLoop: switch f := t.Field(i); f.Name { case genid.SizeCache_goname, genid.SizeCacheA_goname: if f.Type == sizecacheType { - si.sizecacheOffset = offsetOf(f, mi.Exporter) + si.sizecacheOffset = offsetOf(f) si.sizecacheType = f.Type } case genid.WeakFields_goname, genid.WeakFieldsA_goname: if f.Type == weakFieldsType { - si.weakOffset = offsetOf(f, mi.Exporter) + si.weakOffset = offsetOf(f) si.weakType = f.Type } case genid.UnknownFields_goname, genid.UnknownFieldsA_goname: if f.Type == unknownFieldsAType || f.Type == unknownFieldsBType { - si.unknownOffset = offsetOf(f, mi.Exporter) + si.unknownOffset = offsetOf(f) si.unknownType = f.Type } case genid.ExtensionFields_goname, genid.ExtensionFieldsA_goname, genid.ExtensionFieldsB_goname: if f.Type == extensionFieldsType { - si.extensionOffset = offsetOf(f, mi.Exporter) + si.extensionOffset = offsetOf(f) si.extensionType = f.Type } case "lazyFields", "XXX_lazyUnmarshalInfo": - si.lazyOffset = offsetOf(f, mi.Exporter) + si.lazyOffset = offsetOf(f) case "XXX_presence": - si.presenceOffset = offsetOf(f, mi.Exporter) + si.presenceOffset = offsetOf(f) default: for _, s := range strings.Split(f.Tag.Get("protobuf"), ",") { if len(s) > 0 && strings.Trim(s, "0123456789") == "" { diff --git a/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go b/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go index d407dd791e..d8dcd78863 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go +++ b/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go @@ -88,9 +88,7 @@ func opaqueInitHook(mi *MessageInfo) bool { mi.oneofs = map[protoreflect.Name]*oneofInfo{} for i := 0; i < mi.Desc.Oneofs().Len(); i++ { od := mi.Desc.Oneofs().Get(i) - if !od.IsSynthetic() { - mi.oneofs[od.Name()] = makeOneofInfo(od, si.structInfo, mi.Exporter) - } + mi.oneofs[od.Name()] = makeOneofInfoOpaque(mi, od, si.structInfo, mi.Exporter) } mi.denseFields = make([]*fieldInfo, fds.Len()*2) @@ -119,12 +117,32 @@ func opaqueInitHook(mi *MessageInfo) bool { return true } +func makeOneofInfoOpaque(mi *MessageInfo, od protoreflect.OneofDescriptor, si structInfo, x exporter) *oneofInfo { + oi := &oneofInfo{oneofDesc: od} + if od.IsSynthetic() { + fd := od.Fields().Get(0) + index, _ := presenceIndex(mi.Desc, fd) + oi.which = func(p pointer) protoreflect.FieldNumber { + if p.IsNil() { + return 0 + } + if !mi.present(p, index) { + return 0 + } + return od.Fields().Get(0).Number() + } + return oi + } + // Dispatch to non-opaque oneof implementation for non-synthetic oneofs. + return makeOneofInfo(od, si, x) +} + func (mi *MessageInfo) fieldInfoForMapOpaque(si opaqueStructInfo, fd protoreflect.FieldDescriptor, fs reflect.StructField) fieldInfo { ft := fs.Type if ft.Kind() != reflect.Map { panic(fmt.Sprintf("invalid type: got %v, want map kind", ft)) } - fieldOffset := offsetOf(fs, mi.Exporter) + fieldOffset := offsetOf(fs) conv := NewConverter(ft, fd) return fieldInfo{ fieldDesc: fd, @@ -178,7 +196,7 @@ func (mi *MessageInfo) fieldInfoForScalarListOpaque(si opaqueStructInfo, fd prot panic(fmt.Sprintf("invalid type: got %v, want slice kind", ft)) } conv := NewConverter(reflect.PtrTo(ft), fd) - fieldOffset := offsetOf(fs, mi.Exporter) + fieldOffset := offsetOf(fs) index, _ := presenceIndex(mi.Desc, fd) return fieldInfo{ fieldDesc: fd, @@ -228,7 +246,7 @@ func (mi *MessageInfo) fieldInfoForMessageListOpaque(si opaqueStructInfo, fd pro panic(fmt.Sprintf("invalid type: got %v, want slice kind", ft)) } conv := NewConverter(ft, fd) - fieldOffset := offsetOf(fs, mi.Exporter) + fieldOffset := offsetOf(fs) index, _ := presenceIndex(mi.Desc, fd) fieldNumber := fd.Number() return fieldInfo{ @@ -321,7 +339,7 @@ func (mi *MessageInfo) fieldInfoForMessageListOpaqueNoPresence(si opaqueStructIn panic(fmt.Sprintf("invalid type: got %v, want slice kind", ft)) } conv := NewConverter(ft, fd) - fieldOffset := offsetOf(fs, mi.Exporter) + fieldOffset := offsetOf(fs) return fieldInfo{ fieldDesc: fd, has: func(p pointer) bool { @@ -393,7 +411,7 @@ func (mi *MessageInfo) fieldInfoForScalarOpaque(si opaqueStructInfo, fd protoref deref = true } conv := NewConverter(ft, fd) - fieldOffset := offsetOf(fs, mi.Exporter) + fieldOffset := offsetOf(fs) index, _ := presenceIndex(mi.Desc, fd) var getter func(p pointer) protoreflect.Value if !nullable { @@ -462,7 +480,7 @@ func (mi *MessageInfo) fieldInfoForScalarOpaque(si opaqueStructInfo, fd protoref func (mi *MessageInfo) fieldInfoForMessageOpaque(si opaqueStructInfo, fd protoreflect.FieldDescriptor, fs reflect.StructField) fieldInfo { ft := fs.Type conv := NewConverter(ft, fd) - fieldOffset := offsetOf(fs, mi.Exporter) + fieldOffset := offsetOf(fs) index, _ := presenceIndex(mi.Desc, fd) fieldNumber := fd.Number() elemType := fs.Type.Elem() diff --git a/vendor/google.golang.org/protobuf/internal/impl/message_reflect_field.go b/vendor/google.golang.org/protobuf/internal/impl/message_reflect_field.go index a740646205..3cd1fbc21f 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/message_reflect_field.go +++ b/vendor/google.golang.org/protobuf/internal/impl/message_reflect_field.go @@ -76,7 +76,7 @@ func fieldInfoForOneof(fd protoreflect.FieldDescriptor, fs reflect.StructField, isMessage := fd.Message() != nil // TODO: Implement unsafe fast path? - fieldOffset := offsetOf(fs, x) + fieldOffset := offsetOf(fs) return fieldInfo{ // NOTE: The logic below intentionally assumes that oneof fields are // well-formatted. That is, the oneof interface never contains a @@ -152,7 +152,7 @@ func fieldInfoForMap(fd protoreflect.FieldDescriptor, fs reflect.StructField, x conv := NewConverter(ft, fd) // TODO: Implement unsafe fast path? - fieldOffset := offsetOf(fs, x) + fieldOffset := offsetOf(fs) return fieldInfo{ fieldDesc: fd, has: func(p pointer) bool { @@ -205,7 +205,7 @@ func fieldInfoForList(fd protoreflect.FieldDescriptor, fs reflect.StructField, x conv := NewConverter(reflect.PtrTo(ft), fd) // TODO: Implement unsafe fast path? - fieldOffset := offsetOf(fs, x) + fieldOffset := offsetOf(fs) return fieldInfo{ fieldDesc: fd, has: func(p pointer) bool { @@ -269,7 +269,7 @@ func fieldInfoForScalar(fd protoreflect.FieldDescriptor, fs reflect.StructField, } } conv := NewConverter(ft, fd) - fieldOffset := offsetOf(fs, x) + fieldOffset := offsetOf(fs) // Generate specialized getter functions to avoid going through reflect.Value if nullable { @@ -333,7 +333,7 @@ func fieldInfoForScalar(fd protoreflect.FieldDescriptor, fs reflect.StructField, } func fieldInfoForWeakMessage(fd protoreflect.FieldDescriptor, weakOffset offset) fieldInfo { - if !flags.ProtoLegacy { + if !flags.ProtoLegacyWeak { panic("no support for proto1 weak fields") } @@ -410,7 +410,7 @@ func fieldInfoForMessage(fd protoreflect.FieldDescriptor, fs reflect.StructField conv := NewConverter(ft, fd) // TODO: Implement unsafe fast path? - fieldOffset := offsetOf(fs, x) + fieldOffset := offsetOf(fs) return fieldInfo{ fieldDesc: fd, has: func(p pointer) bool { @@ -419,7 +419,7 @@ func fieldInfoForMessage(fd protoreflect.FieldDescriptor, fs reflect.StructField } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if fs.Type.Kind() != reflect.Ptr { - return !isZero(rv) + return !rv.IsZero() } return !rv.IsNil() }, @@ -466,7 +466,7 @@ func makeOneofInfo(od protoreflect.OneofDescriptor, si structInfo, x exporter) * oi := &oneofInfo{oneofDesc: od} if od.IsSynthetic() { fs := si.fieldsByNumber[od.Fields().Get(0).Number()] - fieldOffset := offsetOf(fs, x) + fieldOffset := offsetOf(fs) oi.which = func(p pointer) protoreflect.FieldNumber { if p.IsNil() { return 0 @@ -479,7 +479,7 @@ func makeOneofInfo(od protoreflect.OneofDescriptor, si structInfo, x exporter) * } } else { fs := si.oneofsByName[od.Name()] - fieldOffset := offsetOf(fs, x) + fieldOffset := offsetOf(fs) oi.which = func(p pointer) protoreflect.FieldNumber { if p.IsNil() { return 0 @@ -497,41 +497,3 @@ func makeOneofInfo(od protoreflect.OneofDescriptor, si structInfo, x exporter) * } return oi } - -// isZero is identical to reflect.Value.IsZero. -// TODO: Remove this when Go1.13 is the minimally supported Go version. -func isZero(v reflect.Value) bool { - switch v.Kind() { - 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 math.Float64bits(v.Float()) == 0 - case reflect.Complex64, reflect.Complex128: - c := v.Complex() - return math.Float64bits(real(c)) == 0 && math.Float64bits(imag(c)) == 0 - case reflect.Array: - for i := 0; i < v.Len(); i++ { - if !isZero(v.Index(i)) { - return false - } - } - return true - case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer: - return v.IsNil() - case reflect.String: - return v.Len() == 0 - case reflect.Struct: - for i := 0; i < v.NumField(); i++ { - if !isZero(v.Field(i)) { - return false - } - } - return true - default: - panic(&reflect.ValueError{Method: "reflect.Value.IsZero", Kind: v.Kind()}) - } -} 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 041ebde2de..6bed45e35c 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/pointer_unsafe.go +++ b/vendor/google.golang.org/protobuf/internal/impl/pointer_unsafe.go @@ -22,7 +22,7 @@ type Pointer unsafe.Pointer type offset uintptr // offsetOf returns a field offset for the struct field. -func offsetOf(f reflect.StructField, x exporter) offset { +func offsetOf(f reflect.StructField) offset { return offset(f.Offset) } diff --git a/vendor/google.golang.org/protobuf/internal/version/version.go b/vendor/google.golang.org/protobuf/internal/version/version.go index 3018450df7..f5c06280fe 100644 --- a/vendor/google.golang.org/protobuf/internal/version/version.go +++ b/vendor/google.golang.org/protobuf/internal/version/version.go @@ -52,7 +52,7 @@ import ( const ( Major = 1 Minor = 36 - Patch = 1 + Patch = 3 PreRelease = "" ) diff --git a/vendor/google.golang.org/protobuf/proto/decode.go b/vendor/google.golang.org/protobuf/proto/decode.go index a3b5e142d2..e28d7acb37 100644 --- a/vendor/google.golang.org/protobuf/proto/decode.go +++ b/vendor/google.golang.org/protobuf/proto/decode.go @@ -172,7 +172,7 @@ func (o UnmarshalOptions) unmarshalMessageSlow(b []byte, m protoreflect.Message) var err error if fd == nil { err = errUnknown - } else if flags.ProtoLegacy { + } else if flags.ProtoLegacyWeak { if fd.IsWeak() && fd.Message().IsPlaceholder() { err = errUnknown // weak referent is not linked in } 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 6de31c2ebd..5eaf652176 100644 --- a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go +++ b/vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go @@ -149,7 +149,7 @@ func validateMessageDeclarations(file *filedesc.File, ms []filedesc.Message, mds return errors.New("message field %q under proto3 optional semantics must be within a single element oneof", f.FullName()) } } - if f.IsWeak() && !flags.ProtoLegacy { + if f.IsWeak() && !flags.ProtoLegacyWeak { 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.HasPresence() || !isOptionalMessage(f) || f.ContainingOneof() != nil) { diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/editions.go b/vendor/google.golang.org/protobuf/reflect/protodesc/editions.go index bf0a0ccdee..f55b036959 100644 --- a/vendor/google.golang.org/protobuf/reflect/protodesc/editions.go +++ b/vendor/google.golang.org/protobuf/reflect/protodesc/editions.go @@ -125,16 +125,27 @@ func mergeEditionFeatures(parentDesc protoreflect.Descriptor, child *descriptorp parentFS.IsJSONCompliant = *jf == descriptorpb.FeatureSet_ALLOW } - if goFeatures, ok := proto.GetExtension(child, gofeaturespb.E_Go).(*gofeaturespb.GoFeatures); ok && goFeatures != nil { - if luje := goFeatures.LegacyUnmarshalJsonEnum; luje != nil { - parentFS.GenerateLegacyUnmarshalJSON = *luje - } - if sep := goFeatures.StripEnumPrefix; sep != nil { - parentFS.StripEnumPrefix = int(*sep) - } - if al := goFeatures.ApiLevel; al != nil { - parentFS.APILevel = int(*al) - } + // We must not use proto.GetExtension(child, gofeaturespb.E_Go) + // because that only works for messages we generated, but not for + // dynamicpb messages. See golang/protobuf#1669. + goFeatures := child.ProtoReflect().Get(gofeaturespb.E_Go.TypeDescriptor()) + if !goFeatures.IsValid() { + return parentFS + } + // gf.Interface() could be *dynamicpb.Message or *gofeaturespb.GoFeatures. + gf := goFeatures.Message() + fields := gf.Descriptor().Fields() + + if fd := fields.ByName("legacy_unmarshal_json_enum"); gf.Has(fd) { + parentFS.GenerateLegacyUnmarshalJSON = gf.Get(fd).Bool() + } + + if fd := fields.ByName("strip_enum_prefix"); gf.Has(fd) { + parentFS.StripEnumPrefix = int(gf.Get(fd).Enum()) + } + + if fd := fields.ByName("api_level"); gf.Has(fd) { + parentFS.APILevel = int(gf.Get(fd).Enum()) } return parentFS diff --git a/vendor/gopkg.in/telebot.v3/admin.go b/vendor/gopkg.in/telebot.v3/admin.go index cc8b33a287..22b64c207d 100644 --- a/vendor/gopkg.in/telebot.v3/admin.go +++ b/vendor/gopkg.in/telebot.v3/admin.go @@ -36,6 +36,10 @@ type Rights struct { CanSendVideoNotes bool `json:"can_send_video_notes"` CanSendVoiceNotes bool `json:"can_send_voice_notes"` + CanPostStories bool `json:"can_post_stories"` + CanEditStories bool `json:"can_edit_stories"` + CanDeleteStories bool `json:"can_delete_stories"` + // Independent defines whether the chat permissions are set independently. // If not, the can_send_other_messages and can_add_web_page_previews permissions // will imply the can_send_messages, can_send_audios, can_send_documents, can_send_photos, @@ -106,6 +110,9 @@ func AdminRights() Rights { CanSendVideos: true, CanSendVideoNotes: true, CanSendVoiceNotes: true, + CanPostStories: true, + CanEditStories: true, + CanDeleteStories: true, } } diff --git a/vendor/gopkg.in/telebot.v3/api.go b/vendor/gopkg.in/telebot.v3/api.go index 6ed4eb146f..a66f6211bb 100644 --- a/vendor/gopkg.in/telebot.v3/api.go +++ b/vendor/gopkg.in/telebot.v3/api.go @@ -27,18 +27,21 @@ func (b *Bot) Raw(method string, payload interface{}) ([]byte, error) { return nil, err } - // Cancel the request immediately without waiting for the timeout when bot is about to stop. + // Cancel the request immediately without waiting for the timeout + // when bot is about to stop. // This may become important if doing long polling with long timeout. - exit := make(chan struct{}) - defer close(exit) ctx, cancel := context.WithCancel(context.Background()) defer cancel() go func() { + b.stopMu.RLock() + stopCh := b.stopClient + b.stopMu.RUnlock() + select { - case <-b.stopClient: + case <-stopCh: cancel() - case <-exit: + case <-ctx.Done(): } }() @@ -160,6 +163,19 @@ func addFileToWriter(writer *multipart.Writer, filename, field string, file inte return err } +func (f *File) process(name string, files map[string]File) string { + switch { + case f.InCloud(): + return f.FileID + case f.FileURL != "": + return f.FileURL + case f.OnDisk() || f.FileReader != nil: + files[name] = *f + return "attach://" + name + } + return "" +} + func (b *Bot) sendText(to Recipient, text string, opt *SendOptions) (*Message, error) { params := map[string]string{ "chat_id": to.Recipient(), @@ -238,6 +254,37 @@ func (b *Bot) getUpdates(offset, limit int, timeout time.Duration, allowed []str return resp.Result, nil } +func (b *Bot) forwardCopyMany(to Recipient, msgs []Editable, key string, opts ...*SendOptions) ([]Message, error) { + params := map[string]string{ + "chat_id": to.Recipient(), + } + + embedMessages(params, msgs) + + if len(opts) > 0 { + b.embedSendOptions(params, opts[0]) + } + + data, err := b.Raw(key, params) + if err != nil { + return nil, err + } + + var resp struct { + Result []Message + } + if err := json.Unmarshal(data, &resp); err != nil { + var resp struct { + Result bool + } + if err := json.Unmarshal(data, &resp); err != nil { + return nil, wrapError(err) + } + return nil, wrapError(err) + } + return resp.Result, nil +} + // extractOk checks given result for error. If result is ok returns nil. // In other cases it extracts API error. If error is not presented // in errors.go, it will be prefixed with `unknown` keyword. diff --git a/vendor/gopkg.in/telebot.v3/boost.go b/vendor/gopkg.in/telebot.v3/boost.go new file mode 100644 index 0000000000..7a5897a821 --- /dev/null +++ b/vendor/gopkg.in/telebot.v3/boost.go @@ -0,0 +1,113 @@ +package telebot + +import ( + "encoding/json" + "time" +) + +// Boost contains information about a chat boost. +type Boost struct { + // Unique identifier of the boost. + ID string `json:"boost_id"` + + // Point in time (Unix timestamp) when the chat was boosted. + AddUnixtime int64 `json:"add_date"` + + // Point in time (Unix timestamp) when the boost will automatically expire, + // unless the booster's Telegram Premium subscription is prolonged. + ExpirationUnixtime int64 `json:"expiration_date"` + + // Source of the added boost. + Source *BoostSource `json:"source"` +} + +// AddDate returns the moment of time when the chat has been boosted in local time. +func (c *Boost) AddDate() time.Time { + return time.Unix(c.AddUnixtime, 0) +} + +// ExpirationDate returns the moment of time when the boost of the channel +// will expire in local time. +func (c *Boost) ExpirationDate() time.Time { + return time.Unix(c.ExpirationUnixtime, 0) +} + +// BoostSourceType describes a type of boost. +type BoostSourceType = string + +const ( + BoostPremium BoostSourceType = "premium" + BoostGiftCode BoostSourceType = "gift_code" + BoostGiveaway BoostSourceType = "giveaway" +) + +// BoostSource describes the source of a chat boost. +type BoostSource struct { + // Source of the boost, always (“premium”, “gift_code”, “giveaway”). + Source BoostSourceType `json:"source"` + + // User that boosted the chat. + Booster *User `json:"user"` + + // Identifier of a message in the chat with the giveaway; the message + // could have been deleted already. May be 0 if the message isn't sent yet. + GiveawayMessageID int `json:"giveaway_message_id,omitempty"` + + // (Optional) True, if the giveaway was completed, but there was + // no user to win the prize. + Unclaimed bool `json:"is_unclaimed,omitempty"` +} + +// BoostAdded represents a service message about a user boosting a chat. +type BoostAdded struct { + // Number of boosts added by the user. + Count int `json:"boost_count"` +} + +// BoostUpdated represents a boost added to a chat or changed. +type BoostUpdated struct { + // Chat which was boosted. + Chat *Chat `json:"chat"` + + // Information about the chat boost. + Boost *Boost `json:"boost"` +} + +// BoostRemoved represents a boost removed from a chat. +type BoostRemoved struct { + // Chat which was boosted. + Chat *Chat `json:"chat"` + + // Unique identifier of the boost. + BoostID string `json:"boost_id"` + + // Point in time (Unix timestamp) when the boost was removed. + RemoveUnixtime int64 `json:"remove_date"` + + // Source of the removed boost. + Source *BoostSource `json:"source"` +} + +// UserBoosts gets the list of boosts added to a chat by a user. +// Requires administrator rights in the chat. +func (b *Bot) UserBoosts(chat, user Recipient) ([]Boost, error) { + params := map[string]string{ + "chat_id": chat.Recipient(), + "user_id": user.Recipient(), + } + + data, err := b.Raw("getUserChatBoosts", params) + if err != nil { + return nil, err + } + + var resp struct { + Result struct { + Boosts []Boost `json:"boosts"` + } + } + if err := json.Unmarshal(data, &resp); err != nil { + return nil, wrapError(err) + } + return resp.Result.Boosts, nil +} diff --git a/vendor/gopkg.in/telebot.v3/bot.go b/vendor/gopkg.in/telebot.v3/bot.go index e3a9a41f26..72406a2051 100644 --- a/vendor/gopkg.in/telebot.v3/bot.go +++ b/vendor/gopkg.in/telebot.v3/bot.go @@ -10,6 +10,7 @@ import ( "regexp" "strconv" "strings" + "sync" "time" ) @@ -81,7 +82,9 @@ type Bot struct { parseMode ParseMode stop chan chan struct{} client *http.Client - stopClient chan struct{} + + stopMu sync.RWMutex + stopClient chan struct{} } // Settings represents a utility struct for passing certain @@ -172,22 +175,33 @@ var ( // // b.Handle("/ban", onBan, middleware.Whitelist(ids...)) func (b *Bot) Handle(endpoint interface{}, h HandlerFunc, m ...MiddlewareFunc) { + end := extractEndpoint(endpoint) + if end == "" { + panic("telebot: unsupported endpoint") + } + if len(b.group.middleware) > 0 { m = appendMiddleware(b.group.middleware, m) } - handler := func(c Context) error { + b.handlers[end] = func(c Context) error { return applyMiddleware(h, m...)(c) } +} - switch end := endpoint.(type) { - case string: - b.handlers[end] = handler - case CallbackEndpoint: - b.handlers[end.CallbackUnique()] = handler - default: - panic("telebot: unsupported endpoint") +// Trigger executes the registered handler by the endpoint. +func (b *Bot) Trigger(endpoint interface{}, c Context) error { + end := extractEndpoint(endpoint) + if end == "" { + return fmt.Errorf("telebot: unsupported endpoint") } + + handler, ok := b.handlers[end] + if !ok { + return fmt.Errorf("telebot: no handler found for given endpoint") + } + + return handler(c) } // Start brings bot into motion by consuming incoming @@ -198,10 +212,14 @@ func (b *Bot) Start() { } // do nothing if called twice + b.stopMu.Lock() if b.stopClient != nil { + b.stopMu.Unlock() return } + b.stopClient = make(chan struct{}) + b.stopMu.Unlock() stop := make(chan struct{}) stopConfirm := make(chan struct{}) @@ -221,7 +239,6 @@ func (b *Bot) Start() { close(stop) <-stopConfirm close(confirm) - b.stopClient = nil return } } @@ -229,9 +246,13 @@ func (b *Bot) Start() { // Stop gracefully shuts the poller down. func (b *Bot) Stop() { + b.stopMu.Lock() if b.stopClient != nil { close(b.stopClient) + b.stopClient = nil } + b.stopMu.Unlock() + confirm := make(chan struct{}) b.stop <- confirm <-confirm @@ -270,7 +291,7 @@ func (b *Bot) Send(to Recipient, what interface{}, opts ...interface{}) (*Messag return nil, ErrBadRecipient } - sendOpts := extractOptions(opts) + sendOpts := b.extractOptions(opts) switch object := what.(type) { case string: @@ -290,26 +311,13 @@ func (b *Bot) SendAlbum(to Recipient, a Album, opts ...interface{}) ([]Message, return nil, ErrBadRecipient } - sendOpts := extractOptions(opts) + sendOpts := b.extractOptions(opts) media := make([]string, len(a)) files := make(map[string]File) for i, x := range a { - var ( - repr string - data []byte - file = x.MediaFile() - ) - - switch { - case file.InCloud(): - repr = file.FileID - case file.FileURL != "": - repr = file.FileURL - case file.OnDisk() || file.FileReader != nil: - repr = "attach://" + strconv.Itoa(i) - files[strconv.Itoa(i)] = *file - default: + repr := x.MediaFile().process(strconv.Itoa(i), files) + if repr == "" { return nil, fmt.Errorf("telebot: album entry #%d does not exist", i) } @@ -322,7 +330,7 @@ func (b *Bot) SendAlbum(to Recipient, a Album, opts ...interface{}) ([]Message, im.ParseMode = sendOpts.ParseMode } - data, _ = json.Marshal(im) + data, _ := json.Marshal(im) media[i] = string(data) } @@ -369,7 +377,7 @@ func (b *Bot) SendAlbum(to Recipient, a Album, opts ...interface{}) ([]Message, // Reply behaves just like Send() with an exception of "reply-to" indicator. // This function will panic upon nil Message. func (b *Bot) Reply(to *Message, what interface{}, opts ...interface{}) (*Message, error) { - sendOpts := extractOptions(opts) + sendOpts := b.extractOptions(opts) if sendOpts == nil { sendOpts = &SendOptions{} } @@ -392,7 +400,7 @@ func (b *Bot) Forward(to Recipient, msg Editable, opts ...interface{}) (*Message "message_id": msgID, } - sendOpts := extractOptions(opts) + sendOpts := b.extractOptions(opts) b.embedSendOptions(params, sendOpts) data, err := b.Raw("forwardMessage", params) @@ -403,10 +411,21 @@ func (b *Bot) Forward(to Recipient, msg Editable, opts ...interface{}) (*Message return extractMessage(data) } +// ForwardMany method forwards multiple messages of any kind. +// If some of the specified messages can't be found or forwarded, they are skipped. +// Service messages and messages with protected content can't be forwarded. +// Album grouping is kept for forwarded messages. +func (b *Bot) ForwardMany(to Recipient, msgs []Editable, opts ...*SendOptions) ([]Message, error) { + if to == nil { + return nil, ErrBadRecipient + } + return b.forwardCopyMany(to, msgs, "forwardMessages", opts...) +} + // Copy behaves just like Forward() but the copied message doesn't have a link to the original message (see Bots API). // // This function will panic upon nil Editable. -func (b *Bot) Copy(to Recipient, msg Editable, options ...interface{}) (*Message, error) { +func (b *Bot) Copy(to Recipient, msg Editable, opts ...interface{}) (*Message, error) { if to == nil { return nil, ErrBadRecipient } @@ -418,7 +437,7 @@ func (b *Bot) Copy(to Recipient, msg Editable, options ...interface{}) (*Message "message_id": msgID, } - sendOpts := extractOptions(options) + sendOpts := b.extractOptions(opts) b.embedSendOptions(params, sendOpts) data, err := b.Raw("copyMessage", params) @@ -429,6 +448,20 @@ func (b *Bot) Copy(to Recipient, msg Editable, options ...interface{}) (*Message return extractMessage(data) } +// CopyMany this method makes a copy of messages of any kind. +// If some of the specified messages can't be found or copied, they are skipped. +// Service messages, giveaway messages, giveaway winners messages, and +// invoice messages can't be copied. A quiz poll can be copied only if the value of the field +// correct_option_id is known to the bot. The method is analogous +// to the method forwardMessages, but the copied messages don't have a link to the original message. +// Album grouping is kept for copied messages. +func (b *Bot) CopyMany(to Recipient, msgs []Editable, opts ...*SendOptions) ([]Message, error) { + if to == nil { + return nil, ErrBadRecipient + } + return b.forwardCopyMany(to, msgs, "copyMessages", opts...) +} + // Edit is magic, it lets you change already sent message. // This function will panic upon nil Editable. // @@ -485,7 +518,7 @@ func (b *Bot) Edit(msg Editable, what interface{}, opts ...interface{}) (*Messag params["message_id"] = msgID } - sendOpts := extractOptions(opts) + sendOpts := b.extractOptions(opts) b.embedSendOptions(params, sendOpts) data, err := b.Raw(method, params) @@ -549,7 +582,7 @@ func (b *Bot) EditCaption(msg Editable, caption string, opts ...interface{}) (*M params["message_id"] = msgID } - sendOpts := extractOptions(opts) + sendOpts := b.extractOptions(opts) b.embedSendOptions(params, sendOpts) data, err := b.Raw("editMessageCaption", params) @@ -613,7 +646,7 @@ func (b *Bot) EditMedia(msg Editable, media Inputtable, opts ...interface{}) (*M msgID, chatID := msg.MessageSig() params := make(map[string]string) - sendOpts := extractOptions(opts) + sendOpts := b.extractOptions(opts) b.embedSendOptions(params, sendOpts) im := media.InputMedia() @@ -671,6 +704,16 @@ func (b *Bot) Delete(msg Editable) error { return err } +// DeleteMany deletes multiple messages simultaneously. +// If some of the specified messages can't be found, they are skipped. +func (b *Bot) DeleteMany(msgs []Editable) error { + params := make(map[string]string) + embedMessages(params, msgs) + + _, err := b.Raw("deleteMessages", params) + return err +} + // Notify updates the chat action for recipient. // // Chat action is a status message that recipient would see where @@ -904,7 +947,7 @@ func (b *Bot) StopLiveLocation(msg Editable, opts ...interface{}) (*Message, err "message_id": msgID, } - sendOpts := extractOptions(opts) + sendOpts := b.extractOptions(opts) b.embedSendOptions(params, sendOpts) data, err := b.Raw("stopMessageLiveLocation", params) @@ -928,7 +971,7 @@ func (b *Bot) StopPoll(msg Editable, opts ...interface{}) (*Poll, error) { "message_id": msgID, } - sendOpts := extractOptions(opts) + sendOpts := b.extractOptions(opts) b.embedSendOptions(params, sendOpts) data, err := b.Raw("stopPoll", params) @@ -946,7 +989,7 @@ func (b *Bot) StopPoll(msg Editable, opts ...interface{}) (*Poll, error) { } // Leave makes bot leave a group, supergroup or channel. -func (b *Bot) Leave(chat *Chat) error { +func (b *Bot) Leave(chat Recipient) error { params := map[string]string{ "chat_id": chat.Recipient(), } @@ -967,7 +1010,7 @@ func (b *Bot) Pin(msg Editable, opts ...interface{}) error { "message_id": msgID, } - sendOpts := extractOptions(opts) + sendOpts := b.extractOptions(opts) b.embedSendOptions(params, sendOpts) _, err := b.Raw("pinChatMessage", params) @@ -976,7 +1019,7 @@ func (b *Bot) Pin(msg Editable, opts ...interface{}) error { // Unpin unpins a message in a supergroup or a channel. // It supports tb.Silent option. -func (b *Bot) Unpin(chat *Chat, messageID ...int) error { +func (b *Bot) Unpin(chat Recipient, messageID ...int) error { params := map[string]string{ "chat_id": chat.Recipient(), } @@ -990,7 +1033,7 @@ func (b *Bot) Unpin(chat *Chat, messageID ...int) error { // UnpinAll unpins all messages in a supergroup or a channel. // It supports tb.Silent option. -func (b *Bot) UnpinAll(chat *Chat) error { +func (b *Bot) UnpinAll(chat Recipient) error { params := map[string]string{ "chat_id": chat.Recipient(), } @@ -1151,3 +1194,89 @@ func (b *Bot) Close() (bool, error) { return resp.Result, nil } + +// BotInfo represents a single object of BotName, BotDescription, BotShortDescription instances. +type BotInfo struct { + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + ShortDescription string `json:"short_description,omitempty"` +} + +// SetMyName change's the bot name. +func (b *Bot) SetMyName(name, language string) error { + params := map[string]string{ + "name": name, + "language_code": language, + } + + _, err := b.Raw("setMyName", params) + return err +} + +// MyName returns the current bot name for the given user language. +func (b *Bot) MyName(language string) (*BotInfo, error) { + return b.botInfo(language, "getMyName") +} + +// SetMyDescription change's the bot description, which is shown in the chat +// with the bot if the chat is empty. +func (b *Bot) SetMyDescription(desc, language string) error { + params := map[string]string{ + "description": desc, + "language_code": language, + } + + _, err := b.Raw("setMyDescription", params) + return err +} + +// MyDescription the current bot description for the given user language. +func (b *Bot) MyDescription(language string) (*BotInfo, error) { + return b.botInfo(language, "getMyDescription") +} + +// SetMyShortDescription change's the bot short description, which is shown on +// the bot's profile page and is sent together with the link when users share the bot. +func (b *Bot) SetMyShortDescription(desc, language string) error { + params := map[string]string{ + "short_description": desc, + "language_code": language, + } + + _, err := b.Raw("setMyShortDescription", params) + return err +} + +// MyShortDescription the current bot short description for the given user language. +func (b *Bot) MyShortDescription(language string) (*BotInfo, error) { + return b.botInfo(language, "getMyShortDescription") +} + +func (b *Bot) botInfo(language, key string) (*BotInfo, error) { + params := map[string]string{ + "language_code": language, + } + + data, err := b.Raw(key, params) + if err != nil { + return nil, err + } + + var resp struct { + Result *BotInfo + } + if err := json.Unmarshal(data, &resp); err != nil { + return nil, wrapError(err) + } + return resp.Result, nil +} + +func extractEndpoint(endpoint interface{}) string { + switch end := endpoint.(type) { + case string: + return end + case CallbackEndpoint: + return end.CallbackUnique() + } + return "" +} diff --git a/vendor/gopkg.in/telebot.v3/callback.go b/vendor/gopkg.in/telebot.v3/callback.go index 4bce60a1e4..bfd8a66db8 100644 --- a/vendor/gopkg.in/telebot.v3/callback.go +++ b/vendor/gopkg.in/telebot.v3/callback.go @@ -26,6 +26,15 @@ type Callback struct { // a bad client can send arbitrary data in this field. Data string `json:"data"` + // ChatInstance is a global identifier, uniquely corresponding to + // the chat to which the message with the callback button was sent. + ChatInstance string `json:"chat_instance"` + + // GameShortName is a unique identifier of the game for which a URL + // is requested from the bot when a user presses the Play button of + // that game. GameShortName may be empty + GameShortName string `json:"game_short_name"` + // Unique displays an unique of the button from which the // callback was fired. Sets immediately before the handling, // while the Data field stores only with payload. diff --git a/vendor/gopkg.in/telebot.v3/chat.go b/vendor/gopkg.in/telebot.v3/chat.go index 74d6333bf0..0426739d1b 100644 --- a/vendor/gopkg.in/telebot.v3/chat.go +++ b/vendor/gopkg.in/telebot.v3/chat.go @@ -47,22 +47,32 @@ type Chat struct { Username string `json:"username"` // Returns only in getChat - Bio string `json:"bio,omitempty"` - Photo *ChatPhoto `json:"photo,omitempty"` - Description string `json:"description,omitempty"` - InviteLink string `json:"invite_link,omitempty"` - PinnedMessage *Message `json:"pinned_message,omitempty"` - Permissions *Rights `json:"permissions,omitempty"` - SlowMode int `json:"slow_mode_delay,omitempty"` - StickerSet string `json:"sticker_set_name,omitempty"` - CanSetStickerSet bool `json:"can_set_sticker_set,omitempty"` - LinkedChatID int64 `json:"linked_chat_id,omitempty"` - ChatLocation *ChatLocation `json:"location,omitempty"` - Private bool `json:"has_private_forwards,omitempty"` - Protected bool `json:"has_protected_content,omitempty"` - NoVoiceAndVideo bool `json:"has_restricted_voice_and_video_messages"` - HiddenMembers bool `json:"has_hidden_members,omitempty"` - AggressiveAntiSpam bool `json:"has_aggressive_anti_spam_enabled,omitempty"` + Bio string `json:"bio,omitempty"` + Photo *ChatPhoto `json:"photo,omitempty"` + Description string `json:"description,omitempty"` + InviteLink string `json:"invite_link,omitempty"` + PinnedMessage *Message `json:"pinned_message,omitempty"` + Permissions *Rights `json:"permissions,omitempty"` + Reactions []Reaction `json:"available_reactions"` + SlowMode int `json:"slow_mode_delay,omitempty"` + StickerSet string `json:"sticker_set_name,omitempty"` + CanSetStickerSet bool `json:"can_set_sticker_set,omitempty"` + CustomEmojiSetName string `json:"custom_emoji_sticker_set_name"` + LinkedChatID int64 `json:"linked_chat_id,omitempty"` + ChatLocation *ChatLocation `json:"location,omitempty"` + Private bool `json:"has_private_forwards,omitempty"` + Protected bool `json:"has_protected_content,omitempty"` + NoVoiceAndVideo bool `json:"has_restricted_voice_and_video_messages"` + HasHiddenMembers bool `json:"has_hidden_members,omitempty"` + AggressiveAntiSpam bool `json:"has_aggressive_anti_spam_enabled,omitempty"` + CustomEmojiID string `json:"emoji_status_custom_emoji_id"` + EmojiExpirationUnixtime int64 `json:"emoji_status_expiration_date"` + BackgroundEmojiID string `json:"background_custom_emoji_id"` + AccentColorID int `json:"accent_color_id"` + ProfileAccentColorID int `json:"profile_accent_color_id"` + ProfileBackgroundEmojiID string `json:"profile_background_custom_emoji_id"` + HasVisibleHistory bool `json:"has_visible_history"` + UnrestrictBoosts int `json:"unrestrict_boost_count"` } // Recipient returns chat ID (see Recipient interface). @@ -154,6 +164,9 @@ type ChatMemberUpdate struct { // (Optional) InviteLink which was used by the user to // join the chat; for joining by invite link events only. InviteLink *ChatInviteLink `json:"invite_link"` + + // (Optional) True, if the user joined the chat via a chat folder invite link. + ViaFolderLink bool `json:"via_chat_folder_invite_link"` } // Time returns the moment of the change in local time. @@ -240,6 +253,14 @@ type ChatInviteLink struct { PendingCount int `json:"pending_join_request_count"` } +type Story struct { + // Unique identifier for the story in the chat + ID int `json:"id"` + + // Chat that posted the story + Poster *Chat `json:"chat"` +} + // ExpireDate returns the moment of the link expiration in local time. func (c *ChatInviteLink) ExpireDate() time.Time { return time.Unix(c.ExpireUnixtime, 0) @@ -250,6 +271,11 @@ func (r ChatJoinRequest) Time() time.Time { return time.Unix(r.Unixtime, 0) } +// Time returns the moment of the emoji status expiration. +func (c *Chat) Time() time.Time { + return time.Unix(c.EmojiExpirationUnixtime, 0) +} + // InviteLink should be used to export chat's invite link. func (b *Bot) InviteLink(chat *Chat) (string, error) { params := map[string]string{ diff --git a/vendor/gopkg.in/telebot.v3/context.go b/vendor/gopkg.in/telebot.v3/context.go index 3306c8f737..f5c496561f 100644 --- a/vendor/gopkg.in/telebot.v3/context.go +++ b/vendor/gopkg.in/telebot.v3/context.go @@ -55,6 +55,12 @@ type Context interface { // Topic returns the topic changes. Topic() *Topic + // Boost returns the boost instance. + Boost() *BoostUpdated + + // BoostRemoved returns the boost removed from a chat instance. + BoostRemoved() *BoostRemoved + // Sender returns the current recipient, depending on the context type. // Returns nil if user is not presented. Sender() *User @@ -152,6 +158,12 @@ type Context interface { // See Respond from bot.go. Respond(resp ...*CallbackResponse) error + // RespondText sends a popup response for the current callback query. + RespondText(text string) error + + // RespondAlert sends an alert response for the current callback query. + RespondAlert(text string) error + // Get retrieves data from the context. Get(key string) interface{} @@ -259,6 +271,14 @@ func (c *nativeContext) Topic() *Topic { return nil } +func (c *nativeContext) Boost() *BoostUpdated { + return c.u.Boost +} + +func (c *nativeContext) BoostRemoved() *BoostRemoved { + return c.u.BoostRemoved +} + func (c *nativeContext) Sender() *User { switch { case c.u.Callback != nil: @@ -281,9 +301,16 @@ func (c *nativeContext) Sender() *User { return c.u.ChatMember.Sender case c.u.ChatJoinRequest != nil: return c.u.ChatJoinRequest.Sender - default: - return nil + case c.u.Boost != nil: + if b := c.u.Boost.Boost; b != nil && b.Source != nil { + return b.Source.Booster + } + case c.u.BoostRemoved != nil: + if b := c.u.BoostRemoved; b.Source != nil { + return b.Source.Booster + } } + return nil } func (c *nativeContext) Chat() *Chat { @@ -355,7 +382,7 @@ func (c *nativeContext) Args() []string { case c.u.Message != nil: payload := strings.Trim(c.u.Message.Payload, " ") if payload != "" { - return strings.Split(payload, " ") + return strings.Fields(payload) } case c.u.Callback != nil: return strings.Split(c.u.Callback.Data, "|") @@ -481,6 +508,14 @@ func (c *nativeContext) Respond(resp ...*CallbackResponse) error { return c.b.Respond(c.u.Callback, resp...) } +func (c *nativeContext) RespondText(text string) error { + return c.Respond(&CallbackResponse{Text: text}) +} + +func (c *nativeContext) RespondAlert(text string) error { + return c.Respond(&CallbackResponse{Text: text, ShowAlert: true}) +} + func (c *nativeContext) Answer(resp *QueryResponse) error { if c.u.Query == nil { return errors.New("telebot: context inline query is nil") diff --git a/vendor/gopkg.in/telebot.v3/errors.go b/vendor/gopkg.in/telebot.v3/errors.go index 0197e1934e..23dd3895fb 100644 --- a/vendor/gopkg.in/telebot.v3/errors.go +++ b/vendor/gopkg.in/telebot.v3/errors.go @@ -1,6 +1,7 @@ package telebot import ( + "errors" "fmt" "strings" ) @@ -132,6 +133,7 @@ var ( ErrKickedFromChannel = NewError(403, "Forbidden: bot was kicked from the channel chat") ErrNotStartedByUser = NewError(403, "Forbidden: bot can't initiate conversation with a user") ErrUserIsDeactivated = NewError(403, "Forbidden: user is deactivated") + ErrNotChannelMember = NewError(403, "Forbidden: bot is not a member of the channel chat") ) // Err returns Error instance by given description. @@ -249,11 +251,18 @@ func Err(s string) error { return ErrChannelsTooMuch case ErrChannelsTooMuchUser.ʔ(): return ErrChannelsTooMuchUser + case ErrNotChannelMember.ʔ(): + return ErrNotChannelMember default: return nil } } +// ErrIs checks if the error with given description matches an error err. +func ErrIs(s string, err error) bool { + return errors.Is(err, Err(s)) +} + // wrapError returns new wrapped telebot-related error. func wrapError(err error) error { return fmt.Errorf("telebot: %w", err) diff --git a/vendor/gopkg.in/telebot.v3/giveaway.go b/vendor/gopkg.in/telebot.v3/giveaway.go new file mode 100644 index 0000000000..a0b54e2a5a --- /dev/null +++ b/vendor/gopkg.in/telebot.v3/giveaway.go @@ -0,0 +1,103 @@ +package telebot + +import "time" + +// Giveaway represents a message about a scheduled giveaway. +type Giveaway struct { + // The list of chats which the user must join to participate in the giveaway. + Chats []Chat `json:"chats"` + + // Point in time (Unix timestamp) when winners of the giveaway will be selected. + SelectionUnixtime int64 `json:"winners_selection_date"` + + // The number of users which are supposed to be selected as winners of the giveaway. + WinnerCount int `json:"winner_count"` + + // (Optional) True, if only users who join the chats after the giveaway + // started should be eligible to win. + OnlyNewMembers bool `json:"only_new_members"` + + // (Optional) True, if the list of giveaway winners will be visible to everyone. + HasPublicWinners bool `json:"has_public_winners"` + + // (Optional) Description of additional giveaway prize. + PrizeDescription string `json:"prize_description"` + + // (Optional) A list of two-letter ISO 3166-1 alpha-2 country codes indicating + // the countries from which eligible users for the giveaway must come. + // If empty, then all users can participate in the giveaway. Users with a phone number + // that was bought on Fragment can always participate in giveaways. + CountryCodes []string `json:"country_codes"` + + // (Optional) The number of months the Telegram Premium subscription won from + // the giveaway will be active for. + PremiumMonthCount int `json:"premium_subscription_month_count"` +} + +// SelectionDate returns the moment of when winners of the giveaway were selected in local time. +func (g *Giveaway) SelectionDate() time.Time { + return time.Unix(g.SelectionUnixtime, 0) +} + +// GiveawayWinners object represents a message about the completion of a +// giveaway with public winners. +type GiveawayWinners struct { + // The chat that created the giveaway. + Chat *Chat `json:"chat"` + + // Identifier of the message with the giveaway in the chat. + MessageID int `json:"message_id"` + + // Point in time (Unix timestamp) when winners of the giveaway were selected. + SelectionUnixtime int64 `json:"winners_selection_date"` + + // The number of users which are supposed to be selected as winners of the giveaway. + WinnerCount int `json:"winner_count"` + + // List of up to 100 winners of the giveaway. + Winners []User `json:"winners"` + + // (Optional) The number of other chats the user had to join in order + // to be eligible for the giveaway. + AdditionalChats int `json:"additional_chat_count"` + + // (Optional) The number of months the Telegram Premium subscription won from + // the giveaway will be active for. + PremiumMonthCount int `json:"premium_subscription_month_count"` + + // (Optional) Number of undistributed prizes. + UnclaimedPrizes int `json:"unclaimed_prize_count"` + + // (Optional) True, if only users who had joined the chats after the giveaway started + // were eligible to win. + OnlyNewMembers bool `json:"only_new_members"` + + // (Optional) True, if the giveaway was canceled because the payment for it was refunded. + Refunded bool `json:"was_refunded"` + + // (Optional) Description of additional giveaway prize. + PrizeDescription string `json:"prize_description"` +} + +// SelectionDate returns the moment of when winners of the giveaway +// were selected in local time. +func (g *GiveawayWinners) SelectionDate() time.Time { + return time.Unix(g.SelectionUnixtime, 0) +} + +// GiveawayCreated represents a service message about the creation of a scheduled giveaway. +// Currently holds no information. +type GiveawayCreated struct{} + +// GiveawayCompleted represents a service message about the completion of a +// giveaway without public winners. +type GiveawayCompleted struct { + // Number of winners in the giveaway. + WinnerCount int `json:"winner_count"` + + // (Optional) Number of undistributed prizes. + UnclaimedPrizes int `json:"unclaimed_prize_count"` + + // (Optional) Message with the giveaway that was completed, if it wasn't deleted. + Message *Message `json:"giveaway_message"` +} diff --git a/vendor/gopkg.in/telebot.v3/inline.go b/vendor/gopkg.in/telebot.v3/inline.go index 2a88958220..6a7f43f978 100644 --- a/vendor/gopkg.in/telebot.v3/inline.go +++ b/vendor/gopkg.in/telebot.v3/inline.go @@ -61,6 +61,46 @@ type QueryResponse struct { // (Optional) Parameter for the start message sent to the bot when user // presses the switch button. SwitchPMParameter string `json:"switch_pm_parameter,omitempty"` + + // (Optional) A JSON-serialized object describing a button to be shown + // above inline query results. + Button *QueryResponseButton `json:"button,omitempty"` +} + +// QueryResponseButton represents a button to be shown above inline query results. +// You must use exactly one of the optional fields. +type QueryResponseButton struct { + // Label text on the button + Text string `json:"text"` + + // (Optional) Description of the Web App that will be launched when the + // user presses the button. The Web App will be able to switch back to the + // inline mode using the method switchInlineQuery inside the Web App. + WebApp *WebApp `json:"web_app"` + + // (Optional) Deep-linking parameter for the /start message sent to the bot + // when a user presses the button. 1-64 characters, only A-Z, a-z, 0-9, _ and - are allowed. + Start string `json:"start_parameter"` +} + +// SwitchInlineQuery represents an inline button that switches the current +// user to inline mode in a chosen chat, with an optional default inline query. +type SwitchInlineQuery struct { + // (Optional) The default inline query to be inserted in the input field. + // If left empty, only the bot's username will be inserted. + Query string `json:"query"` + + // (Optional) True, if private chats with users can be chosen. + AllowUserChats bool `json:"allow_user_chats"` + + // (Optional) True, if private chats with bots can be chosen. + AllowBotChats bool `json:"allow_bot_chats"` + + // (Optional) True, if group and supergroup chats can be chosen. + AllowGroupChats bool `json:"allow_group_chats"` + + // (Optional) True, if channel chats can be chosen. + AllowChannelChats bool `json:"allow_channel_chats"` } // InlineResult represents a result of an inline query that was chosen @@ -131,6 +171,8 @@ func inferIQR(result Result) error { r.Type = "voice" case *StickerResult: r.Type = "sticker" + case *GameResult: + r.Type = "game" default: return fmt.Errorf("telebot: result %v is not supported", result) } diff --git a/vendor/gopkg.in/telebot.v3/inline_types.go b/vendor/gopkg.in/telebot.v3/inline_types.go index d93cffc209..9b05751908 100644 --- a/vendor/gopkg.in/telebot.v3/inline_types.go +++ b/vendor/gopkg.in/telebot.v3/inline_types.go @@ -60,6 +60,16 @@ func (r *ResultBase) Process(b *Bot) { } } +// GameResult represents a game. Game is a content type +// supported by Telegram, which can be sent back to the +// user as a result for an inline query. +type GameResult struct { + ResultBase + + // ShortName is a unique identifier of the game. + ShortName string `json:"game_short_name"` +} + // ArticleResult represents a link to an article or web page. type ArticleResult struct { ResultBase @@ -81,13 +91,13 @@ type ArticleResult struct { Description string `json:"description,omitempty"` // Optional. URL of the thumbnail for the result. - ThumbURL string `json:"thumb_url,omitempty"` + ThumbURL string `json:"thumbnail_url,omitempty"` // Optional. Width of the thumbnail for the result. - ThumbWidth int `json:"thumb_width,omitempty"` + ThumbWidth int `json:"thumbnail_width,omitempty"` // Optional. Height of the thumbnail for the result. - ThumbHeight int `json:"thumb_height,omitempty"` + ThumbHeight int `json:"thumbnail_height,omitempty"` } // AudioResult represents a link to an mp3 audio file. @@ -130,13 +140,13 @@ type ContactResult struct { LastName string `json:"last_name,omitempty"` // Optional. URL of the thumbnail for the result. - ThumbURL string `json:"thumb_url,omitempty"` + ThumbURL string `json:"thumbnail_url,omitempty"` // Optional. Width of the thumbnail for the result. - ThumbWidth int `json:"thumb_width,omitempty"` + ThumbWidth int `json:"thumbnail_width,omitempty"` // Optional. Height of the thumbnail for the result. - ThumbHeight int `json:"thumb_height,omitempty"` + ThumbHeight int `json:"thumbnail_height,omitempty"` } // DocumentResult represents a link to a file. @@ -160,13 +170,13 @@ type DocumentResult struct { Description string `json:"description,omitempty"` // Optional. URL of the thumbnail (jpeg only) for the file. - ThumbURL string `json:"thumb_url,omitempty"` + ThumbURL string `json:"thumbnail_url,omitempty"` // Optional. Width of the thumbnail for the result. - ThumbWidth int `json:"thumb_width,omitempty"` + ThumbWidth int `json:"thumbnail_width,omitempty"` // Optional. Height of the thumbnail for the result. - ThumbHeight int `json:"thumb_height,omitempty"` + ThumbHeight int `json:"thumbnail_height,omitempty"` // If Cache != "", it'll be used instead Cache string `json:"document_file_id,omitempty"` @@ -189,11 +199,11 @@ type GifResult struct { Duration int `json:"gif_duration,omitempty"` // URL of the static thumbnail for the result (jpeg or gif). - ThumbURL string `json:"thumb_url"` + ThumbURL string `json:"thumbnail_url"` // Optional. MIME type of the thumbnail, must be one of // “image/jpeg”, “image/gif”, or “video/mp4”. - ThumbMIME string `json:"thumb_mime_type,omitempty"` + ThumbMIME string `json:"thumbnail_mime_type,omitempty"` // Optional. Title for the result. Title string `json:"title,omitempty"` @@ -215,7 +225,7 @@ type LocationResult struct { Title string `json:"title"` // Optional. Url of the thumbnail for the result. - ThumbURL string `json:"thumb_url,omitempty"` + ThumbURL string `json:"thumbnail_url,omitempty"` } // Mpeg4GifResult represents a link to a video animation @@ -236,11 +246,11 @@ type Mpeg4GifResult struct { Duration int `json:"mpeg4_duration,omitempty"` // URL of the static thumbnail (jpeg or gif) for the result. - ThumbURL string `json:"thumb_url,omitempty"` + ThumbURL string `json:"thumbnail_url,omitempty"` // Optional. MIME type of the thumbnail, must be one of // “image/jpeg”, “image/gif”, or “video/mp4”. - ThumbMIME string `json:"thumb_mime_type,omitempty"` + ThumbMIME string `json:"thumbnail_mime_type,omitempty"` // Optional. Title for the result. Title string `json:"title,omitempty"` @@ -276,7 +286,7 @@ type PhotoResult struct { Caption string `json:"caption,omitempty"` // URL of the thumbnail for the photo. - ThumbURL string `json:"thumb_url"` + ThumbURL string `json:"thumbnail_url"` // If Cache != "", it'll be used instead Cache string `json:"photo_file_id,omitempty"` @@ -298,13 +308,13 @@ type VenueResult struct { FoursquareID string `json:"foursquare_id,omitempty"` // Optional. URL of the thumbnail for the result. - ThumbURL string `json:"thumb_url,omitempty"` + ThumbURL string `json:"thumbnail_url,omitempty"` // Optional. Width of the thumbnail for the result. - ThumbWidth int `json:"thumb_width,omitempty"` + ThumbWidth int `json:"thumbnail_width,omitempty"` // Optional. Height of the thumbnail for the result. - ThumbHeight int `json:"thumb_height,omitempty"` + ThumbHeight int `json:"thumbnail_height,omitempty"` } // VideoResult represents a link to a page containing an embedded @@ -319,7 +329,7 @@ type VideoResult struct { MIME string `json:"mime_type"` // URL of the thumbnail (jpeg only) for the video. - ThumbURL string `json:"thumb_url"` + ThumbURL string `json:"thumbnail_url"` // Title for the result. Title string `json:"title"` diff --git a/vendor/gopkg.in/telebot.v3/input_types.go b/vendor/gopkg.in/telebot.v3/input_types.go index 8186c0727c..8e49a7f516 100644 --- a/vendor/gopkg.in/telebot.v3/input_types.go +++ b/vendor/gopkg.in/telebot.v3/input_types.go @@ -12,12 +12,12 @@ type InputTextMessageContent struct { // Text of the message to be sent, 1-4096 characters. Text string `json:"message_text"` - // Optional. Send Markdown or HTML, if you want Telegram apps to show + // (Optional) Send Markdown or HTML, if you want Telegram apps to show // bold, italic, fixed-width text or inline URLs in your bot's message. ParseMode string `json:"parse_mode,omitempty"` - // Optional. Disables link previews for links in the sent message. - DisablePreview bool `json:"disable_web_page_preview"` + // (Optional) Link preview generation options for the message. + PreviewOptions *PreviewOptions `json:"link_preview_options,omitempty"` } func (input *InputTextMessageContent) IsInputMessageContent() bool { diff --git a/vendor/gopkg.in/telebot.v3/markup.go b/vendor/gopkg.in/telebot.v3/markup.go index 29236db34e..b45990c521 100644 --- a/vendor/gopkg.in/telebot.v3/markup.go +++ b/vendor/gopkg.in/telebot.v3/markup.go @@ -220,7 +220,7 @@ type ReplyButton struct { Contact bool `json:"request_contact,omitempty"` Location bool `json:"request_location,omitempty"` Poll PollType `json:"request_poll,omitempty"` - User *ReplyRecipient `json:"request_user,omitempty"` + User *ReplyRecipient `json:"request_users,omitempty"` Chat *ReplyRecipient `json:"request_chat,omitempty"` WebApp *WebApp `json:"web_app,omitempty"` } @@ -244,8 +244,9 @@ func (pt PollType) MarshalJSON() ([]byte, error) { type ReplyRecipient struct { ID int32 `json:"request_id"` - Bot *bool `json:"user_is_bot,omitempty"` // user only, optional - Premium *bool `json:"user_is_premium,omitempty"` // user only, optional + Bot *bool `json:"user_is_bot,omitempty"` // user only, optional + Premium *bool `json:"user_is_premium,omitempty"` // user only, optional + Quantity int `json:"max_quantity,omitempty"` // user only, optional Channel bool `json:"chat_is_channel,omitempty"` // chat only, required Forum *bool `json:"chat_is_forum,omitempty"` // chat only, optional @@ -271,13 +272,14 @@ type InlineButton struct { // It will be used as a callback endpoint. Unique string `json:"unique,omitempty"` - Text string `json:"text"` - URL string `json:"url,omitempty"` - Data string `json:"callback_data,omitempty"` - InlineQuery string `json:"switch_inline_query,omitempty"` - InlineQueryChat string `json:"switch_inline_query_current_chat"` - Login *Login `json:"login_url,omitempty"` - WebApp *WebApp `json:"web_app,omitempty"` + Text string `json:"text"` + URL string `json:"url,omitempty"` + Data string `json:"callback_data,omitempty"` + InlineQuery string `json:"switch_inline_query,omitempty"` + InlineQueryChat string `json:"switch_inline_query_current_chat"` + InlineQueryChosenChat *SwitchInlineQuery `json:"switch_inline_query_chosen_chat,omitempty"` + Login *Login `json:"login_url,omitempty"` + WebApp *WebApp `json:"web_app,omitempty"` } // MarshalJSON implements json.Marshaler interface. diff --git a/vendor/gopkg.in/telebot.v3/media.go b/vendor/gopkg.in/telebot.v3/media.go index d161aa58a0..bdce55579c 100644 --- a/vendor/gopkg.in/telebot.v3/media.go +++ b/vendor/gopkg.in/telebot.v3/media.go @@ -19,7 +19,7 @@ type InputMedia struct { Type string `json:"type"` Media string `json:"media"` Caption string `json:"caption"` - Thumbnail string `json:"thumb,omitempty"` + Thumbnail string `json:"thumbnail,omitempty"` ParseMode string `json:"parse_mode,omitempty"` Entities Entities `json:"caption_entities,omitempty"` Width int `json:"width,omitempty"` @@ -45,6 +45,24 @@ type Inputtable interface { // Album lets you group multiple media into a single message. type Album []Inputtable +func (a Album) SetCaption(caption string) { + if len(a) < 1 { + return + } + switch a[0].MediaType() { + case "audio": + a[0].(*Audio).Caption = caption + case "video": + a[0].(*Video).Caption = caption + case "document": + a[0].(*Document).Caption = caption + case "photo": + a[0].(*Photo).Caption = caption + case "animation": + a[0].(*Animation).Caption = caption + } +} + // Photo object represents a single photo file. type Photo struct { File @@ -113,7 +131,7 @@ type Audio struct { // (Optional) Caption string `json:"caption,omitempty"` - Thumbnail *Photo `json:"thumb,omitempty"` + Thumbnail *Photo `json:"thumbnail,omitempty"` Title string `json:"title,omitempty"` Performer string `json:"performer,omitempty"` MIME string `json:"mime_type,omitempty"` @@ -145,7 +163,7 @@ type Document struct { File // (Optional) - Thumbnail *Photo `json:"thumb,omitempty"` + Thumbnail *Photo `json:"thumbnail,omitempty"` Caption string `json:"caption,omitempty"` MIME string `json:"mime_type"` FileName string `json:"file_name,omitempty"` @@ -179,7 +197,7 @@ type Video struct { // (Optional) Caption string `json:"caption,omitempty"` - Thumbnail *Photo `json:"thumb,omitempty"` + Thumbnail *Photo `json:"thumbnail,omitempty"` Streaming bool `json:"supports_streaming,omitempty"` MIME string `json:"mime_type,omitempty"` FileName string `json:"file_name,omitempty"` @@ -215,7 +233,7 @@ type Animation struct { // (Optional) Caption string `json:"caption,omitempty"` - Thumbnail *Photo `json:"thumb,omitempty"` + Thumbnail *Photo `json:"thumbnail,omitempty"` MIME string `json:"mime_type,omitempty"` FileName string `json:"file_name,omitempty"` } @@ -265,7 +283,7 @@ type VideoNote struct { Duration int `json:"duration"` // (Optional) - Thumbnail *Photo `json:"thumb,omitempty"` + Thumbnail *Photo `json:"thumbnail,omitempty"` Length int `json:"length,omitempty"` } @@ -280,17 +298,18 @@ func (v *VideoNote) MediaFile() *File { // Sticker object represents a WebP image, so-called sticker. type Sticker struct { File + Type StickerSetType `json:"type"` Width int `json:"width"` Height int `json:"height"` Animated bool `json:"is_animated"` Video bool `json:"is_video"` - Thumbnail *Photo `json:"thumb"` + Thumbnail *Photo `json:"thumbnail"` Emoji string `json:"emoji"` SetName string `json:"set_name"` - MaskPosition *MaskPosition `json:"mask_position"` PremiumAnimation *File `json:"premium_animation"` - Type StickerSetType `json:"type"` + MaskPosition *MaskPosition `json:"mask_position"` CustomEmoji string `json:"custom_emoji_id"` + Repaint bool `json:"needs_repainting"` } func (s *Sticker) MediaType() string { diff --git a/vendor/gopkg.in/telebot.v3/message.go b/vendor/gopkg.in/telebot.v3/message.go index 82997569a3..d7d239bc5e 100644 --- a/vendor/gopkg.in/telebot.v3/message.go +++ b/vendor/gopkg.in/telebot.v3/message.go @@ -46,6 +46,9 @@ type Message struct { // For forwarded messages, unixtime of the original message. OriginalUnixtime int `json:"forward_date"` + // For information about the original message for forwarded messages. + Origin *MessageOrigin `json:"forward_origin"` + // Message is a channel post that was automatically forwarded to the connected discussion group. AutomaticForward bool `json:"is_automatic_forward"` @@ -56,9 +59,23 @@ type Message struct { // itself is a reply. ReplyTo *Message `json:"reply_to_message"` + // (Optional) For replies to a story, the original story + Story *Story `json:"story"` + + // (Optional) Information about the message that is being replied to, + // which may come from another chat or forum topic. + ExternalReplyInfo *ExternalReplyInfo `json:"external_reply"` + + // (Optional) For replies that quote part of the original message, + // the quoted part of the message. + Quote *TextQuote `json:"quote"` + // Shows through which bot the message was sent. Via *User `json:"via_bot"` + // For replies to a story, the original story. + ReplyToStory *Story `json:"reply_to_story"` + // (Optional) Time of last edit in Unix. LastEdit int64 `json:"edit_date"` @@ -87,6 +104,10 @@ type Message struct { // etc. that appear in the text. Entities Entities `json:"entities,omitempty"` + // (Optional) PreviewOptions used for link preview generation for the message, + // if it is a text message and link preview options were changed. + PreviewOptions *PreviewOptions `json:"link_preview_options,omitempty"` + // Some messages containing media, may as well have a caption. Caption string `json:"caption,omitempty"` @@ -115,7 +136,7 @@ type Message struct { // For a video, information about it. Video *Video `json:"video"` - // For a animation, information about it. + // For an animation, information about it. Animation *Animation `json:"animation"` // For a contact, contact information itself. @@ -136,6 +157,18 @@ type Message struct { // For a dice, information about it. Dice *Dice `json:"dice"` + // (Optional) The message is a scheduled giveaway message. + Giveaway *Giveaway `json:"giveaway"` + + // (Optional) A giveaway with public winners was completed. + GiveawayWinners *GiveawayWinners `json:"giveaway_winners"` + + // (Optional) Service message: a scheduled giveaway was created. + GiveawayCreated *GiveawayCreated `json:"giveaway_created"` + + // (Optional) Service message: a giveaway without public winners was completed. + GiveawayCompleted *GiveawayCompleted `json:"giveaway_completed"` + // For a service message, represents a user, // that just got added to chat, this message came from. // @@ -230,7 +263,7 @@ type Message struct { Payment *Payment `json:"successful_payment"` // For a service message, a user was shared with the bot. - UserShared *RecipientShared `json:"user_shared,omitempty"` + UserShared *RecipientShared `json:"users_shared,omitempty"` // For a service message, a chat was shared with the bot. ChatShared *RecipientShared `json:"chat_shared,omitempty"` @@ -263,6 +296,13 @@ type Message struct { // Inline keyboard attached to the message. ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"` + // Service message: user boosted the chat. + BoostAdded *BoostAdded `json:"boost_added"` + + // If the sender of the message boosted the chat, the number of boosts + // added by the user. + SenderBoostCount int `json:"sender_boost_count"` + // Service message: forum topic created TopicCreated *Topic `json:"forum_topic_created,omitempty"` @@ -336,9 +376,10 @@ const ( EntityTextLink EntityType = "text_link" EntitySpoiler EntityType = "spoiler" EntityCustomEmoji EntityType = "custom_emoji" + EntityBlockquote EntityType = "blockquote" ) -// Entities is used to set message's text entities as a send option. +// Entities are used to set message's text entities as a send option. type Entities []MessageEntity // ProximityAlert sent whenever a user in the chat triggers @@ -354,6 +395,11 @@ type AutoDeleteTimer struct { Unixtime int `json:"message_auto_delete_time"` } +// Inaccessible shows whether the message is InaccessibleMessage object. +func (m *Message) Inaccessible() bool { + return m.Sender == nil +} + // MessageSig satisfies Editable interface (see Editable.) func (m *Message) MessageSig() (string, int64) { return strconv.Itoa(m.ID), m.Chat.ID @@ -461,3 +507,215 @@ func (m *Message) Media() Media { return nil } } + +// MessageReaction object represents a change of a reaction on a message performed by a user. +type MessageReaction struct { + // The chat containing the message the user reacted to. + Chat *Chat `json:"chat"` + + // Unique identifier of the message inside the chat. + MessageID int `json:"message_id"` + + // (Optional) The user that changed the reaction, + // if the user isn't anonymous + User *User `json:"user"` + + // (Optional) The chat on behalf of which the reaction was changed, + // if the user is anonymous. + ActorChat *Chat `json:"actor_chat"` + + // Date of the change in Unix time. + DateUnixtime int64 `json:"date"` + + // Previous list of reaction types that were set by the user. + OldReaction []Reaction `json:"old_reaction"` + + // New list of reaction types that have been set by the user. + NewReaction []Reaction `json:"new_reaction"` +} + +func (mu *MessageReaction) Time() time.Time { + return time.Unix(mu.DateUnixtime, 0) +} + +// MessageReactionCount represents reaction changes on a message with +// anonymous reactions. +type MessageReactionCount struct { + // The chat containing the message. + Chat *Chat `json:"chat"` + + // Unique message identifier inside the chat. + MessageID int `json:"message_id"` + + // Date of the change in Unix time. + DateUnixtime int64 `json:"date"` + + // List of reactions that are present on the message. + Reactions *ReactionCount `json:"reactions"` +} + +// Time returns the moment of change in local time. +func (mc *MessageReactionCount) Time() time.Time { + return time.Unix(mc.DateUnixtime, 0) +} + +// TextQuote contains information about the quoted part of a message that is +// replied to by the given message. +type TextQuote struct { + // Text of the quoted part of a message that is replied to by the given message. + Text string `json:"text"` + + // (Optional) Special entities that appear in the quote. + // Currently, only bold, italic, underline, strikethrough, spoiler, + // and custom_emoji entities are kept in quotes. + Entities []MessageEntity `json:"entities"` + + // Approximate quote position in the original message in UTF-16 code units + // as specified by the sender. + Position int `json:"position"` + + // (Optional) True, if the quote was chosen manually by the message sender. + // Otherwise, the quote was added automatically by the server. + Manual bool `json:"is_manual"` +} + +// MessageOrigin a message reference that has been sent originally by a known user. +type MessageOrigin struct { + // Type of the message origin, always “channel”. + Type string `json:"type"` + + // Date the message was sent originally in Unix time. + DateUnixtime int64 `json:"date"` + + // User that sent the message originally. + Sender *User `json:"sender_user,omitempty"` + + // Name of the user that sent the message originally. + SenderUsername string `json:"sender_user_name,omitempty"` + + // Chat that sent the message originally. + SenderChat *Chat `json:"sender_chat,omitempty"` + + // Channel chat to which the message was originally sent. + Chat *Chat `json:"chat,omitempty"` + + // Unique message identifier inside the chat. + MessageID int `json:"message_id,omitempty"` + + // (Optional) For messages originally sent by an anonymous chat administrator, + // original message author signature. + Signature string `json:"author_signature,omitempty"` +} + +// Time returns the moment of message that was sent originally in local time. +func (mo *MessageOrigin) Time() time.Time { + return time.Unix(mo.DateUnixtime, 0) +} + +// ExternalReplyInfo contains information about a message that is being replied to, +// which may come from another chat or forum topic. +type ExternalReplyInfo struct { + // Origin of the message replied to by the given message. + Origin *MessageOrigin `json:"origin"` + + // (Optional) Chat the original message belongs to. + // Available only if the chat is a supergroup or a channel. + Chat *Chat `json:"chat"` + + // (Optional) Unique message identifier inside the original chat. + // Available only if the original chat is a supergroup or a channel. + MessageID int `json:"message_id"` + + // (Optional) ReactionOptions used for link preview generation for the original message, + // if it is a text message. + PreviewOptions *PreviewOptions `json:"link_preview_options"` + + // (Optional) Message is an animation, information about the animation. + Animation *Animation `json:"animation"` + + // (Optional) Message is an audio file, information about the file. + Audio *Audio `json:"audio"` + + // (Optional) Message is a general file, information about the file. + Document *Document `json:"document"` + + // (Optional) Message is a photo, available sizes of the photo. + Photo []Photo `json:"photo"` + + // (Optional) Message is a sticker, information about the sticker. + Sticker *Sticker `json:"sticker"` + + // (Optional) Message is a forwarded story. + Story *Story `json:"story"` + + // (Optional) Message is a video, information about the video. + Video *Video `json:"video"` + + // (Optional) Message is a video note, information about the video message. + Note *VideoNote `json:"video_note"` + + // (Optional) Message is a voice message, information about the file. + Voice *Voice `json:"voice"` + + // (Optional) True, if the message media is covered by a spoiler animation. + HasMediaSpoiler bool `json:"has_media_spoiler"` + + // (Optional) Message is a shared contact, information about the contact. + Contact *Contact `json:"contact"` + + // (Optional) Message is a dice with random value. + Dice *Dice `json:"dice"` + + //( Optional) Message is a game, information about the game. + Game *Game `json:"game"` + + // (Optional) Message is a venue, information about the venue. + Venue *Venue `json:"venue"` + + // (Optional) Message is a native poll, information about the poll. + Poll *Poll `json:"poll"` + + // (Optional) Message is a shared location, information about the location. + Location *Location `json:"location"` + + // (Optional) Message is an invoice for a payment, information about the invoice. + Invoice *Invoice `json:"invoice"` + + // (Optional) Message is a scheduled giveaway, information about the giveaway. + Giveaway *Giveaway `json:"giveaway"` + + // (Optional) A giveaway with public winners was completed. + GiveawayWinners *GiveawayWinners `json:"giveaway_winners"` +} + +// ReplyParams describes reply parameters for the message that is being sent. +type ReplyParams struct { + // Identifier of the message that will be replied to in the current chat, + // or in the chat chat_id if it is specified. + MessageID int `json:"message_id"` + + // (Optional) If the message to be replied to is from a different chat, + // unique identifier for the chat or username of the channel. + ChatID int64 `json:"chat_id"` + + // Optional. Pass True if the message should be sent even if the specified message + // to be replied to is not found; can be used only for replies in the + // same chat and forum topic. + AllowWithoutReply bool `json:"allow_sending_without_reply"` + + // (Optional) Quoted part of the message to be replied to; 0-1024 characters after + // entities parsing. The quote must be an exact substring of the message to be replied to, + // including bold, italic, underline, strikethrough, spoiler, and custom_emoji entities. + // The message will fail to send if the quote isn't found in the original message. + Quote string `json:"quote"` + + // (Optional) Mode for parsing entities in the quote. + QuoteParseMode ParseMode `json:"quote_parse_mode"` + + // (Optional) A JSON-serialized list of special entities that appear in the quote. + // It can be specified instead of quote_parse_mode. + QuoteEntities []MessageEntity `json:"quote_entities"` + + // (Optional) Position of the quote in the original message in UTF-16 code units. + QuotePosition int `json:"quote_position"` +} diff --git a/vendor/gopkg.in/telebot.v3/options.go b/vendor/gopkg.in/telebot.v3/options.go index 56e0d9c295..20c75dec6d 100644 --- a/vendor/gopkg.in/telebot.v3/options.go +++ b/vendor/gopkg.in/telebot.v3/options.go @@ -84,6 +84,8 @@ type SendOptions struct { // HasSpoiler marks the message as containing a spoiler. HasSpoiler bool + // ReplyParams Describes the message to reply to + ReplyParams *ReplyParams } func (og *SendOptions) copy() *SendOptions { @@ -94,8 +96,10 @@ func (og *SendOptions) copy() *SendOptions { return &cp } -func extractOptions(how []interface{}) *SendOptions { - opts := &SendOptions{} +func (b *Bot) extractOptions(how []interface{}) *SendOptions { + opts := &SendOptions{ + ParseMode: b.parseMode, + } for _, prop := range how { switch opt := prop.(type) { @@ -105,6 +109,8 @@ func extractOptions(how []interface{}) *SendOptions { if opt != nil { opts.ReplyMarkup = opt.copy() } + case *ReplyParams: + opts.ReplyParams = opt case Option: switch opt { case NoPreview: @@ -146,10 +152,6 @@ func extractOptions(how []interface{}) *SendOptions { } func (b *Bot) embedSendOptions(params map[string]string, opt *SendOptions) { - if b.parseMode != ModeDefault { - params["parse_mode"] = b.parseMode - } - if opt == nil { return } @@ -198,7 +200,7 @@ func (b *Bot) embedSendOptions(params map[string]string, opt *SendOptions) { if opt.ThreadID != 0 { params["message_thread_id"] = strconv.Itoa(opt.ThreadID) } - + if opt.HasSpoiler { params["spoiler"] = "true" } @@ -224,3 +226,45 @@ func processButtons(keys [][]InlineButton) { } } } + +// PreviewOptions describes the options used for link preview generation. +type PreviewOptions struct { + // (Optional) True, if the link preview is disabled. + Disabled bool `json:"is_disabled"` + + // (Optional) URL to use for the link preview. If empty, then the first URL + // found in the message text will be used. + URL string `json:"url"` + + // (Optional) True, if the media in the link preview is supposed to be shrunk; + // ignored if the URL isn't explicitly specified or media size change. + // isn't supported for the preview. + SmallMedia bool `json:"prefer_small_media"` + + // (Optional) True, if the media in the link preview is supposed to be enlarged; + // ignored if the URL isn't explicitly specified or media size change. + // isn't supported for the preview. + LargeMedia bool `json:"prefer_large_media"` + + // (Optional) True, if the link preview must be shown above the message text; + // otherwise, the link preview will be shown below the message text. + AboveText bool `json:"show_above_text"` +} + +func embedMessages(params map[string]string, msgs []Editable) { + ids := make([]string, 0, len(msgs)) + + _, chatID := msgs[0].MessageSig() + for _, msg := range msgs { + msgID, _ := msg.MessageSig() + ids = append(ids, msgID) + } + + data, err := json.Marshal(ids) + if err != nil { + return + } + + params["message_ids"] = string(data) + params["chat_id"] = strconv.FormatInt(chatID, 10) +} diff --git a/vendor/gopkg.in/telebot.v3/poll.go b/vendor/gopkg.in/telebot.v3/poll.go index 8e2e5091db..48018e7b0b 100644 --- a/vendor/gopkg.in/telebot.v3/poll.go +++ b/vendor/gopkg.in/telebot.v3/poll.go @@ -49,6 +49,7 @@ type PollOption struct { type PollAnswer struct { PollID string `json:"poll_id"` Sender *User `json:"user"` + Chat *Chat `json:"voter_chat"` Options []int `json:"option_ids"` } diff --git a/vendor/gopkg.in/telebot.v3/poller.go b/vendor/gopkg.in/telebot.v3/poller.go index d45f2a5435..60b4211101 100644 --- a/vendor/gopkg.in/telebot.v3/poller.go +++ b/vendor/gopkg.in/telebot.v3/poller.go @@ -2,12 +2,32 @@ package telebot import "time" +var AllowedUpdates = []string{ + "message", + "edited_message", + "channel_post", + "edited_channel_post", + "message_reaction", + "message_reaction_count", + "inline_query", + "chosen_inline_result", + "callback_query", + "shipping_query", + "pre_checkout_query", + "poll", + "poll_answer", + "my_chat_member", + "chat_member", + "chat_join_request", + "chat_boost", + "removed_chat_boost", +} + // Poller is a provider of Updates. // // All pollers must implement Poll(), which accepts bot // pointer and subscription channel and start polling // synchronously straight away. -// type Poller interface { // Poll is supposed to take the bot object // subscription channel and start polling @@ -70,7 +90,6 @@ func (p *LongPoller) Poll(b *Bot, dest chan Update, stop chan struct{}) { // handling, banning or whatever. // // For heavy middleware, use increased capacity. -// type MiddlewarePoller struct { Capacity int // Default: 1 Poller Poller diff --git a/vendor/gopkg.in/telebot.v3/react.go b/vendor/gopkg.in/telebot.v3/react.go new file mode 100644 index 0000000000..7b01ca7f67 --- /dev/null +++ b/vendor/gopkg.in/telebot.v3/react.go @@ -0,0 +1,67 @@ +package telebot + +import ( + "encoding/json" +) + +// Reaction describes the type of reaction. +// Describes an instance of ReactionTypeCustomEmoji and ReactionTypeEmoji. +type Reaction struct { + // Type of the reaction, always “emoji” + Type string `json:"type"` + + // Reaction emoji. + Emoji string `json:"emoji,omitempty"` + + // Custom emoji identifier. + CustomEmoji string `json:"custom_emoji_id,omitempty"` +} + +// ReactionCount represents a reaction added to a message along +// with the number of times it was added. +type ReactionCount struct { + // Type of the reaction. + Type Reaction `json:"type"` + + // Number of times the reaction was added. + Count int `json:"total_count"` +} + +// ReactionOptions represents an object of reaction options. +type ReactionOptions struct { + // List of reaction types to set on the message. + Reactions []Reaction `json:"reaction"` + + // Pass True to set the reaction with a big animation. + Big bool `json:"is_big"` +} + +// React changes the chosen reactions on a message. Service messages can't be +// reacted to. Automatically forwarded messages from a channel to its discussion group have +// the same available reactions as messages in the channel. +func (b *Bot) React(to Recipient, msg Editable, opts ...ReactionOptions) error { + if to == nil { + return ErrBadRecipient + } + msgID, _ := msg.MessageSig() + + params := map[string]string{ + "chat_id": to.Recipient(), + "message_id": msgID, + } + + if len(opts) > 0 { + opt := opts[0] + + if len(opt.Reactions) > 0 { + data, _ := json.Marshal(opt.Reactions) + params["reaction"] = string(data) + } + if opt.Big { + params["is_big"] = "true" + } + } + + _, err := b.Raw("setMessageReaction", params) + return err +} diff --git a/vendor/gopkg.in/telebot.v3/sendable.go b/vendor/gopkg.in/telebot.v3/sendable.go index ecaae7fed1..4d7d9a5e00 100644 --- a/vendor/gopkg.in/telebot.v3/sendable.go +++ b/vendor/gopkg.in/telebot.v3/sendable.go @@ -115,6 +115,7 @@ func (d *Document) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error func (s *Sticker) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) { params := map[string]string{ "chat_id": to.Recipient(), + "emoji": s.Emoji, } b.embedSendOptions(params, opt) @@ -401,7 +402,7 @@ func (g *Game) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) { func thumbnailToFilemap(thumb *Photo) map[string]File { if thumb != nil { - return map[string]File{"thumb": thumb.File} + return map[string]File{"thumbnail": thumb.File} } return nil } diff --git a/vendor/gopkg.in/telebot.v3/sticker.go b/vendor/gopkg.in/telebot.v3/sticker.go new file mode 100644 index 0000000000..7fd060c030 --- /dev/null +++ b/vendor/gopkg.in/telebot.v3/sticker.go @@ -0,0 +1,306 @@ +package telebot + +import ( + "encoding/json" + "errors" + "fmt" + "strconv" +) + +type ( + StickerSetType = string + StickerSetFormat = string + MaskFeature = string +) + +const ( + StickerRegular StickerSetType = "regular" + StickerMask StickerSetType = "mask" + StickerCustomEmoji StickerSetType = "custom_emoji" +) + +const ( + StickerStatic StickerSetFormat = "static" + StickerAnimated StickerSetFormat = "animated" + StickerVideo StickerSetFormat = "video" +) + +const ( + MaskForehead MaskFeature = "forehead" + MaskEyes MaskFeature = "eyes" + MaskMouth MaskFeature = "mouth" + MaskChin MaskFeature = "chin" +) + +// StickerSet represents a sticker set. +type StickerSet struct { + Type StickerSetType `json:"sticker_type"` + Format StickerSetFormat `json:"sticker_format"` + Name string `json:"name"` + Title string `json:"title"` + Animated bool `json:"is_animated"` + Video bool `json:"is_video"` + Stickers []Sticker `json:"stickers"` + Thumbnail *Photo `json:"thumbnail"` + Emojis string `json:"emojis"` + ContainsMasks bool `json:"contains_masks"` // FIXME: can be removed + MaskPosition *MaskPosition `json:"mask_position"` + Repaint bool `json:"needs_repainting"` + + // Input is a field used in createNewStickerSet method to specify a list + // of pre-defined stickers of type InputSticker to add to the set. + Input []InputSticker +} + +type InputSticker struct { + File + Sticker string `json:"sticker"` + MaskPosition *MaskPosition `json:"mask_position"` + Emojis []string `json:"emoji_list"` + Keywords []string `json:"keywords"` +} + +// MaskPosition describes the position on faces where +// a mask should be placed by default. +type MaskPosition struct { + Feature MaskFeature `json:"point"` + XShift float32 `json:"x_shift"` + YShift float32 `json:"y_shift"` + Scale float32 `json:"scale"` +} + +// UploadSticker uploads a sticker file for later use. +func (b *Bot) UploadSticker(to Recipient, format StickerSetFormat, f File) (*File, error) { + params := map[string]string{ + "user_id": to.Recipient(), + "sticker_format": format, + } + + data, err := b.sendFiles("uploadStickerFile", map[string]File{"0": f}, params) + if err != nil { + return nil, err + } + + var resp struct { + Result File + } + if err := json.Unmarshal(data, &resp); err != nil { + return nil, wrapError(err) + } + return &resp.Result, nil +} + +// StickerSet returns a sticker set on success. +func (b *Bot) StickerSet(name string) (*StickerSet, error) { + data, err := b.Raw("getStickerSet", map[string]string{"name": name}) + if err != nil { + return nil, err + } + + var resp struct { + Result *StickerSet + } + if err := json.Unmarshal(data, &resp); err != nil { + return nil, wrapError(err) + } + return resp.Result, nil +} + +// CreateStickerSet creates a new sticker set. +func (b *Bot) CreateStickerSet(of Recipient, set *StickerSet) error { + files := make(map[string]File) + for i, s := range set.Input { + repr := s.File.process(strconv.Itoa(i), files) + if repr == "" { + return fmt.Errorf("telebot: sticker #%d does not exist", i+1) + } + set.Input[i].Sticker = repr + } + + data, _ := json.Marshal(set.Input) + + params := map[string]string{ + "user_id": of.Recipient(), + "name": set.Name, + "title": set.Title, + "sticker_format": set.Format, + "stickers": string(data), + } + if set.Type != "" { + params["sticker_type"] = set.Type + } + if set.Repaint { + params["needs_repainting"] = "true" + } + + _, err := b.sendFiles("createNewStickerSet", files, params) + return err +} + +// AddStickerToSet adds a new sticker to the existing sticker set. +func (b *Bot) AddStickerToSet(of Recipient, name string, sticker InputSticker) error { + files := make(map[string]File) + repr := sticker.File.process("0", files) + if repr == "" { + return errors.New("telebot: sticker does not exist") + } + + sticker.Sticker = repr + data, _ := json.Marshal(sticker) + + params := map[string]string{ + "user_id": of.Recipient(), + "name": name, + "sticker": string(data), + } + + _, err := b.sendFiles("addStickerToSet", files, params) + return err +} + +// SetStickerPosition moves a sticker in set to a specific position. +func (b *Bot) SetStickerPosition(sticker string, position int) error { + params := map[string]string{ + "sticker": sticker, + "position": strconv.Itoa(position), + } + + _, err := b.Raw("setStickerPositionInSet", params) + return err +} + +// DeleteSticker deletes a sticker from a set created by the bot. +func (b *Bot) DeleteSticker(sticker string) error { + _, err := b.Raw("deleteStickerFromSet", map[string]string{"sticker": sticker}) + return err + +} + +// SetStickerSetThumb sets a thumbnail of the sticker set. +// Animated thumbnails can be set for animated sticker sets only. +// +// Thumbnail must be a PNG image, up to 128 kilobytes in size +// and have width and height exactly 100px, or a TGS animation +// up to 32 kilobytes in size. +// +// Animated sticker set thumbnail can't be uploaded via HTTP URL. +func (b *Bot) SetStickerSetThumb(of Recipient, set *StickerSet) error { + if set.Thumbnail == nil { + return errors.New("telebot: thumbnail is required") + } + + files := make(map[string]File) + repr := set.Thumbnail.File.process("thumb", files) + if repr == "" { + return errors.New("telebot: thumbnail does not exist") + } + + params := map[string]string{ + "user_id": of.Recipient(), + "name": set.Name, + "thumbnail": repr, + } + + _, err := b.sendFiles("setStickerSetThumbnail", files, params) + return err +} + +// SetStickerSetTitle sets the title of a created sticker set. +func (b *Bot) SetStickerSetTitle(s StickerSet) error { + params := map[string]string{ + "name": s.Name, + "title": s.Title, + } + + _, err := b.Raw("setStickerSetTitle", params) + return err +} + +// DeleteStickerSet deletes a sticker set that was created by the bot. +func (b *Bot) DeleteStickerSet(name string) error { + params := map[string]string{"name": name} + + _, err := b.Raw("deleteStickerSet", params) + return err +} + +// SetStickerEmojis changes the list of emoji assigned to a regular or custom emoji sticker. +func (b *Bot) SetStickerEmojis(sticker string, emojis []string) error { + data, err := json.Marshal(emojis) + if err != nil { + return err + } + + params := map[string]string{ + "sticker": sticker, + "emoji_list": string(data), + } + + _, err = b.Raw("setStickerEmojiList", params) + return err +} + +// SetStickerKeywords changes search keywords assigned to a regular or custom emoji sticker. +func (b *Bot) SetStickerKeywords(sticker string, keywords []string) error { + mk, err := json.Marshal(keywords) + if err != nil { + return err + } + + params := map[string]string{ + "sticker": sticker, + "keywords": string(mk), + } + + _, err = b.Raw("setStickerKeywords", params) + return err +} + +// SetStickerMaskPosition changes the mask position of a mask sticker. +func (b *Bot) SetStickerMaskPosition(sticker string, mask MaskPosition) error { + data, err := json.Marshal(mask) + if err != nil { + return err + } + + params := map[string]string{ + "sticker": sticker, + "mask_position": string(data), + } + + _, err = b.Raw("setStickerMaskPosition", params) + return err +} + +// CustomEmojiStickers returns the information about custom emoji stickers by their ids. +func (b *Bot) CustomEmojiStickers(ids []string) ([]Sticker, error) { + data, _ := json.Marshal(ids) + + params := map[string]string{ + "custom_emoji_ids": string(data), + } + + data, err := b.Raw("getCustomEmojiStickers", params) + if err != nil { + return nil, err + } + + var resp struct { + Result []Sticker + } + if err := json.Unmarshal(data, &resp); err != nil { + return nil, wrapError(err) + } + return resp.Result, nil +} + +// SetCustomEmojiStickerSetThumb sets the thumbnail of a custom emoji sticker set. +func (b *Bot) SetCustomEmojiStickerSetThumb(name, id string) error { + params := map[string]string{ + "name": name, + "custom_emoji_id": id, + } + + _, err := b.Raw("setCustomEmojiStickerSetThumbnail", params) + return err +} diff --git a/vendor/gopkg.in/telebot.v3/stickers.go b/vendor/gopkg.in/telebot.v3/stickers.go deleted file mode 100644 index 3e0a6264b0..0000000000 --- a/vendor/gopkg.in/telebot.v3/stickers.go +++ /dev/null @@ -1,212 +0,0 @@ -package telebot - -import ( - "encoding/json" - "strconv" -) - -type StickerSetType = string - -const ( - StickerRegular = "regular" - StickerMask = "mask" - StickerCustomEmoji = "custom_emoji" -) - -// StickerSet represents a sticker set. -type StickerSet struct { - Type StickerSetType `json:"sticker_type"` - Name string `json:"name"` - Title string `json:"title"` - Animated bool `json:"is_animated"` - Video bool `json:"is_video"` - Stickers []Sticker `json:"stickers"` - Thumbnail *Photo `json:"thumb"` - PNG *File `json:"png_sticker"` - TGS *File `json:"tgs_sticker"` - WebM *File `json:"webm_sticker"` - Emojis string `json:"emojis"` - ContainsMasks bool `json:"contains_masks"` // FIXME: can be removed - MaskPosition *MaskPosition `json:"mask_position"` -} - -// MaskPosition describes the position on faces where -// a mask should be placed by default. -type MaskPosition struct { - Feature MaskFeature `json:"point"` - XShift float32 `json:"x_shift"` - YShift float32 `json:"y_shift"` - Scale float32 `json:"scale"` -} - -// MaskFeature defines sticker mask position. -type MaskFeature string - -const ( - FeatureForehead MaskFeature = "forehead" - FeatureEyes MaskFeature = "eyes" - FeatureMouth MaskFeature = "mouth" - FeatureChin MaskFeature = "chin" -) - -// UploadSticker uploads a PNG file with a sticker for later use. -func (b *Bot) UploadSticker(to Recipient, png *File) (*File, error) { - files := map[string]File{ - "png_sticker": *png, - } - params := map[string]string{ - "user_id": to.Recipient(), - } - - data, err := b.sendFiles("uploadStickerFile", files, params) - if err != nil { - return nil, err - } - - var resp struct { - Result File - } - if err := json.Unmarshal(data, &resp); err != nil { - return nil, wrapError(err) - } - return &resp.Result, nil -} - -// StickerSet returns a sticker set on success. -func (b *Bot) StickerSet(name string) (*StickerSet, error) { - data, err := b.Raw("getStickerSet", map[string]string{"name": name}) - if err != nil { - return nil, err - } - - var resp struct { - Result *StickerSet - } - if err := json.Unmarshal(data, &resp); err != nil { - return nil, wrapError(err) - } - return resp.Result, nil -} - -// CreateStickerSet creates a new sticker set. -func (b *Bot) CreateStickerSet(to Recipient, s StickerSet) error { - files := make(map[string]File) - if s.PNG != nil { - files["png_sticker"] = *s.PNG - } - if s.TGS != nil { - files["tgs_sticker"] = *s.TGS - } - if s.WebM != nil { - files["webm_sticker"] = *s.WebM - } - - params := map[string]string{ - "user_id": to.Recipient(), - "sticker_type": s.Type, - "name": s.Name, - "title": s.Title, - "emojis": s.Emojis, - "contains_masks": strconv.FormatBool(s.ContainsMasks), - } - - if s.MaskPosition != nil { - data, _ := json.Marshal(&s.MaskPosition) - params["mask_position"] = string(data) - } - - _, err := b.sendFiles("createNewStickerSet", files, params) - return err -} - -// AddSticker adds a new sticker to the existing sticker set. -func (b *Bot) AddSticker(to Recipient, s StickerSet) error { - files := make(map[string]File) - if s.PNG != nil { - files["png_sticker"] = *s.PNG - } else if s.TGS != nil { - files["tgs_sticker"] = *s.TGS - } else if s.WebM != nil { - files["webm_sticker"] = *s.WebM - } - - params := map[string]string{ - "user_id": to.Recipient(), - "name": s.Name, - "emojis": s.Emojis, - } - - if s.MaskPosition != nil { - data, _ := json.Marshal(&s.MaskPosition) - params["mask_position"] = string(data) - } - - _, err := b.sendFiles("addStickerToSet", files, params) - return err -} - -// SetStickerPosition moves a sticker in set to a specific position. -func (b *Bot) SetStickerPosition(sticker string, position int) error { - params := map[string]string{ - "sticker": sticker, - "position": strconv.Itoa(position), - } - - _, err := b.Raw("setStickerPositionInSet", params) - return err -} - -// DeleteSticker deletes a sticker from a set created by the bot. -func (b *Bot) DeleteSticker(sticker string) error { - _, err := b.Raw("deleteStickerFromSet", map[string]string{"sticker": sticker}) - return err - -} - -// SetStickerSetThumb sets a thumbnail of the sticker set. -// Animated thumbnails can be set for animated sticker sets only. -// -// Thumbnail must be a PNG image, up to 128 kilobytes in size -// and have width and height exactly 100px, or a TGS animation -// up to 32 kilobytes in size. -// -// Animated sticker set thumbnail can't be uploaded via HTTP URL. -// -func (b *Bot) SetStickerSetThumb(to Recipient, s StickerSet) error { - files := make(map[string]File) - if s.PNG != nil { - files["thumb"] = *s.PNG - } else if s.TGS != nil { - files["thumb"] = *s.TGS - } - - params := map[string]string{ - "name": s.Name, - "user_id": to.Recipient(), - } - - _, err := b.sendFiles("setStickerSetThumb", files, params) - return err -} - -// CustomEmojiStickers returns the information about custom emoji stickers by their ids. -func (b *Bot) CustomEmojiStickers(ids []string) ([]Sticker, error) { - data, _ := json.Marshal(ids) - - params := map[string]string{ - "custom_emoji_ids": string(data), - } - - data, err := b.Raw("getCustomEmojiStickers", params) - if err != nil { - return nil, err - } - - var resp struct { - Result []Sticker - } - if err := json.Unmarshal(data, &resp); err != nil { - return nil, wrapError(err) - } - return resp.Result, nil -} diff --git a/vendor/gopkg.in/telebot.v3/telebot.go b/vendor/gopkg.in/telebot.v3/telebot.go index b8271e9a4d..4705587590 100644 --- a/vendor/gopkg.in/telebot.v3/telebot.go +++ b/vendor/gopkg.in/telebot.v3/telebot.go @@ -109,6 +109,9 @@ const ( OnVideoChatEnded = "\avideo_chat_ended" OnVideoChatParticipants = "\avideo_chat_participants_invited" OnVideoChatScheduled = "\avideo_chat_scheduled" + + OnBoost = "\aboost_updated" + OnBoostRemoved = "\aboost_removed" ) // ChatAction is a client-side status indicating bot activity. diff --git a/vendor/gopkg.in/telebot.v3/topic.go b/vendor/gopkg.in/telebot.v3/topic.go index d81fe9a943..4f6935dff8 100644 --- a/vendor/gopkg.in/telebot.v3/topic.go +++ b/vendor/gopkg.in/telebot.v3/topic.go @@ -6,10 +6,10 @@ import ( ) type Topic struct { - Name string `json:"name"` - IconColor int `json:"icon_color"` - IconCustomEmojiID string `json:"icon_custom_emoji_id"` - ThreadID int `json:"message_thread_id"` + Name string `json:"name"` + IconColor int `json:"icon_color"` + IconCustomEmoji string `json:"icon_custom_emoji_id"` + ThreadID int `json:"message_thread_id"` } // CreateTopic creates a topic in a forum supergroup chat. @@ -22,8 +22,8 @@ func (b *Bot) CreateTopic(chat *Chat, topic *Topic) (*Topic, error) { if topic.IconColor != 0 { params["icon_color"] = strconv.Itoa(topic.IconColor) } - if topic.IconCustomEmojiID != "" { - params["icon_custom_emoji_id"] = topic.IconCustomEmojiID + if topic.IconCustomEmoji != "" { + params["icon_custom_emoji_id"] = topic.IconCustomEmoji } data, err := b.Raw("createForumTopic", params) @@ -50,8 +50,8 @@ func (b *Bot) EditTopic(chat *Chat, topic *Topic) error { if topic.Name != "" { params["name"] = topic.Name } - if topic.IconCustomEmojiID != "" { - params["icon_custom_emoji_id"] = topic.IconCustomEmojiID + if topic.IconCustomEmoji != "" { + params["icon_custom_emoji_id"] = topic.IconCustomEmoji } _, err := b.Raw("editForumTopic", params) @@ -170,3 +170,15 @@ func (b *Bot) UnhideGeneralTopic(chat *Chat) error { _, err := b.Raw("unhideGeneralForumTopic", params) return err } + +// UnpinAllGeneralTopicMessages clears the list of pinned messages in a General forum topic. +// The bot must be an administrator in the chat for this to work and must have the +// can_pin_messages administrator right in the supergroup. +func (b *Bot) UnpinAllGeneralTopicMessages(chat *Chat) error { + params := map[string]interface{}{ + "chat_id": chat.Recipient(), + } + + _, err := b.Raw("unpinAllGeneralForumTopicMessages", params) + return err +} diff --git a/vendor/gopkg.in/telebot.v3/update.go b/vendor/gopkg.in/telebot.v3/update.go index 12a065ab22..63396dd4ba 100644 --- a/vendor/gopkg.in/telebot.v3/update.go +++ b/vendor/gopkg.in/telebot.v3/update.go @@ -6,20 +6,24 @@ import "strings" type Update struct { ID int `json:"update_id"` - Message *Message `json:"message,omitempty"` - EditedMessage *Message `json:"edited_message,omitempty"` - ChannelPost *Message `json:"channel_post,omitempty"` - EditedChannelPost *Message `json:"edited_channel_post,omitempty"` - Callback *Callback `json:"callback_query,omitempty"` - Query *Query `json:"inline_query,omitempty"` - InlineResult *InlineResult `json:"chosen_inline_result,omitempty"` - ShippingQuery *ShippingQuery `json:"shipping_query,omitempty"` - PreCheckoutQuery *PreCheckoutQuery `json:"pre_checkout_query,omitempty"` - Poll *Poll `json:"poll,omitempty"` - PollAnswer *PollAnswer `json:"poll_answer,omitempty"` - MyChatMember *ChatMemberUpdate `json:"my_chat_member,omitempty"` - ChatMember *ChatMemberUpdate `json:"chat_member,omitempty"` - ChatJoinRequest *ChatJoinRequest `json:"chat_join_request,omitempty"` + Message *Message `json:"message,omitempty"` + EditedMessage *Message `json:"edited_message,omitempty"` + ChannelPost *Message `json:"channel_post,omitempty"` + EditedChannelPost *Message `json:"edited_channel_post,omitempty"` + MessageReaction *MessageReaction `json:"message_reaction"` + MessageReactionCount *MessageReactionCount `json:"message_reaction_count"` + Callback *Callback `json:"callback_query,omitempty"` + Query *Query `json:"inline_query,omitempty"` + InlineResult *InlineResult `json:"chosen_inline_result,omitempty"` + ShippingQuery *ShippingQuery `json:"shipping_query,omitempty"` + PreCheckoutQuery *PreCheckoutQuery `json:"pre_checkout_query,omitempty"` + Poll *Poll `json:"poll,omitempty"` + PollAnswer *PollAnswer `json:"poll_answer,omitempty"` + MyChatMember *ChatMemberUpdate `json:"my_chat_member,omitempty"` + ChatMember *ChatMemberUpdate `json:"chat_member,omitempty"` + ChatJoinRequest *ChatJoinRequest `json:"chat_join_request,omitempty"` + Boost *BoostUpdated `json:"chat_boost"` + BoostRemoved *BoostRemoved `json:"removed_chat_boost"` } // ProcessUpdate processes a single incoming update. @@ -308,6 +312,16 @@ func (b *Bot) ProcessUpdate(u Update) { b.handle(OnChatJoinRequest, c) return } + + if u.Boost != nil { + b.handle(OnBoost, c) + return + } + + if u.BoostRemoved != nil { + b.handle(OnBoostRemoved, c) + return + } } func (b *Bot) handle(end string, c Context) bool { diff --git a/vendor/gopkg.in/telebot.v3/web_app.go b/vendor/gopkg.in/telebot.v3/web_app.go index e5c9070f2c..b0d3956176 100644 --- a/vendor/gopkg.in/telebot.v3/web_app.go +++ b/vendor/gopkg.in/telebot.v3/web_app.go @@ -20,5 +20,7 @@ type WebAppData struct { // WebAppAccessAllowed represents a service message about a user allowing // a bot to write messages after adding the bot to the attachment menu or launching a Web App from a link. type WriteAccessAllowed struct { - WebAppName string `json:"web_app_name,omitempty"` + WebAppName string `json:"web_app_name,omitempty"` + FromRequest bool `json:"from_request,omitempty"` + FromAttachmentMenu bool `json:"from_attachment_menu,omitempty"` } diff --git a/vendor/modules.txt b/vendor/modules.txt index e9f5b61da7..d1df4441d5 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -119,7 +119,7 @@ github.com/VictoriaMetrics/fastcache ## explicit github.com/alecthomas/template github.com/alecthomas/template/parse -# github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30 +# github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b ## explicit; go 1.15 github.com/alecthomas/units # github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 @@ -142,7 +142,7 @@ github.com/armon/go-metrics/prometheus # github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 ## explicit; go 1.13 github.com/asaskevich/govalidator -# github.com/aws/aws-sdk-go v1.55.5 +# github.com/aws/aws-sdk-go v1.55.6 ## explicit; go 1.19 github.com/aws/aws-sdk-go/aws github.com/aws/aws-sdk-go/aws/auth/bearer @@ -277,7 +277,6 @@ github.com/aws/smithy-go/transport/http/internal/io github.com/bboreham/go-loser # github.com/benbjohnson/clock v1.3.5 ## explicit; go 1.15 -github.com/benbjohnson/clock # github.com/beorn7/perks v1.0.1 ## explicit; go 1.11 github.com/beorn7/perks/quantile @@ -296,6 +295,9 @@ github.com/cenkalti/backoff/v4 # github.com/cespare/xxhash/v2 v2.3.0 ## explicit; go 1.11 github.com/cespare/xxhash/v2 +# github.com/coder/quartz v0.1.2 +## explicit; go 1.21.8 +github.com/coder/quartz # github.com/coreos/go-semver v0.3.0 ## explicit github.com/coreos/go-semver/semver @@ -429,7 +431,7 @@ github.com/go-redis/redis/v8/internal/pool github.com/go-redis/redis/v8/internal/proto github.com/go-redis/redis/v8/internal/rand github.com/go-redis/redis/v8/internal/util -# github.com/goccy/go-json v0.10.3 +# github.com/goccy/go-json v0.10.4 ## explicit; go 1.19 github.com/goccy/go-json github.com/goccy/go-json/internal/decoder @@ -460,7 +462,7 @@ github.com/gogo/status # github.com/golang-jwt/jwt/v5 v5.2.1 ## explicit; go 1.18 github.com/golang-jwt/jwt/v5 -# github.com/golang-migrate/migrate/v4 v4.18.1 +# github.com/golang-migrate/migrate/v4 v4.18.2 ## explicit; go 1.22.0 github.com/golang-migrate/migrate/v4 github.com/golang-migrate/migrate/v4/database @@ -548,8 +550,8 @@ github.com/grpc-ecosystem/go-grpc-middleware # github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 ## explicit; go 1.19 github.com/grpc-ecosystem/go-grpc-middleware/v2 -# github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 -## explicit; go 1.22.7 +# github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 +## explicit; go 1.22.0 github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule github.com/grpc-ecosystem/grpc-gateway/v2/runtime github.com/grpc-ecosystem/grpc-gateway/v2/utilities @@ -595,8 +597,8 @@ github.com/hashicorp/memberlist # github.com/hashicorp/serf v0.10.1 ## explicit; go 1.12 github.com/hashicorp/serf/coordinate -# github.com/jessevdk/go-flags v1.5.0 -## explicit; go 1.15 +# github.com/jessevdk/go-flags v1.6.1 +## explicit; go 1.20 github.com/jessevdk/go-flags # github.com/jmespath/go-jmespath v0.4.0 ## explicit; go 1.14 @@ -631,8 +633,8 @@ github.com/klauspost/compress/snappy github.com/klauspost/compress/zlib github.com/klauspost/compress/zstd github.com/klauspost/compress/zstd/internal/xxhash -# github.com/klauspost/cpuid/v2 v2.2.8 -## explicit; go 1.15 +# github.com/klauspost/cpuid/v2 v2.2.9 +## explicit; go 1.20 github.com/klauspost/cpuid/v2 # github.com/kylelemons/godebug v1.1.0 ## explicit; go 1.11 @@ -678,7 +680,7 @@ github.com/miekg/dns # github.com/minio/md5-simd v1.1.2 ## explicit; go 1.14 github.com/minio/md5-simd -# github.com/minio/minio-go/v7 v7.0.82 +# github.com/minio/minio-go/v7 v7.0.84 ## explicit; go 1.22 github.com/minio/minio-go/v7 github.com/minio/minio-go/v7/pkg/cors @@ -725,7 +727,7 @@ github.com/oklog/run # github.com/oklog/ulid v1.3.1 ## explicit github.com/oklog/ulid -# github.com/opentracing-contrib/go-grpc v0.1.0 +# github.com/opentracing-contrib/go-grpc v0.1.1 ## explicit; go 1.22.7 github.com/opentracing-contrib/go-grpc # github.com/opentracing-contrib/go-stdlib v1.1.0 @@ -749,8 +751,8 @@ github.com/pmezard/go-difflib/difflib # github.com/prometheus-community/prom-label-proxy v0.8.1-0.20240127162815-c1195f9aabc0 ## explicit; go 1.20 github.com/prometheus-community/prom-label-proxy/injectproxy -# github.com/prometheus/alertmanager v0.27.0 -## explicit; go 1.21 +# github.com/prometheus/alertmanager v0.28.0 +## explicit; go 1.22.0 github.com/prometheus/alertmanager/api github.com/prometheus/alertmanager/api/metrics github.com/prometheus/alertmanager/api/v2 @@ -775,8 +777,8 @@ github.com/prometheus/alertmanager/config github.com/prometheus/alertmanager/dispatch github.com/prometheus/alertmanager/featurecontrol github.com/prometheus/alertmanager/inhibit -github.com/prometheus/alertmanager/matchers/compat -github.com/prometheus/alertmanager/matchers/parse +github.com/prometheus/alertmanager/matcher/compat +github.com/prometheus/alertmanager/matcher/parse github.com/prometheus/alertmanager/nflog github.com/prometheus/alertmanager/nflog/nflogpb github.com/prometheus/alertmanager/notify @@ -822,18 +824,19 @@ github.com/prometheus/client_golang/prometheus/testutil/promlint/validations # github.com/prometheus/client_model v0.6.1 ## explicit; go 1.19 github.com/prometheus/client_model/go -# github.com/prometheus/common v0.61.0 +# github.com/prometheus/common v0.62.0 ## explicit; go 1.21 github.com/prometheus/common/config github.com/prometheus/common/expfmt github.com/prometheus/common/helpers/templates github.com/prometheus/common/model +github.com/prometheus/common/promslog github.com/prometheus/common/route github.com/prometheus/common/version # github.com/prometheus/common/sigv4 v0.1.0 ## explicit; go 1.15 github.com/prometheus/common/sigv4 -# github.com/prometheus/exporter-toolkit v0.12.0 +# github.com/prometheus/exporter-toolkit v0.13.2 ## explicit; go 1.22 github.com/prometheus/exporter-toolkit/web # github.com/prometheus/procfs v0.15.1 @@ -904,7 +907,7 @@ github.com/prometheus/prometheus/web/api/v1 github.com/redis/rueidis github.com/redis/rueidis/internal/cmds github.com/redis/rueidis/internal/util -# github.com/rs/cors v1.11.0 +# github.com/rs/cors v1.11.1 ## explicit; go 1.13 github.com/rs/cors github.com/rs/cors/internal @@ -928,8 +931,8 @@ github.com/sercand/kuberesolver/v5 github.com/shurcooL/httpfs/filter github.com/shurcooL/httpfs/union github.com/shurcooL/httpfs/vfsutil -# github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 -## explicit +# github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92 +## explicit; go 1.19 github.com/shurcooL/vfsgen # github.com/sirupsen/logrus v1.9.3 ## explicit; go 1.13 @@ -1045,7 +1048,7 @@ github.com/thanos-io/thanos/pkg/tracing/interceptors github.com/thanos-io/thanos/pkg/tracing/migration github.com/thanos-io/thanos/pkg/tracing/tracing_middleware github.com/thanos-io/thanos/pkg/tracing/util/metautils -# github.com/tjhop/slog-gokit v0.1.2 +# github.com/tjhop/slog-gokit v0.1.3 ## explicit; go 1.21 github.com/tjhop/slog-gokit # github.com/uber/jaeger-client-go v2.30.0+incompatible @@ -1105,7 +1108,7 @@ github.com/yuin/gopher-lua/pm # github.com/zhangyunhao116/umap v0.0.0-20221211160557-cb7705fafa39 ## explicit; go 1.13 github.com/zhangyunhao116/umap -# go.etcd.io/etcd/api/v3 v3.5.17 +# go.etcd.io/etcd/api/v3 v3.5.18 ## explicit; go 1.22 go.etcd.io/etcd/api/v3/authpb go.etcd.io/etcd/api/v3/etcdserverpb @@ -1113,7 +1116,7 @@ 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.17 +# go.etcd.io/etcd/client/pkg/v3 v3.5.18 ## explicit; go 1.22 go.etcd.io/etcd/client/pkg/v3/fileutil go.etcd.io/etcd/client/pkg/v3/logutil @@ -1121,7 +1124,7 @@ go.etcd.io/etcd/client/pkg/v3/systemd go.etcd.io/etcd/client/pkg/v3/tlsutil go.etcd.io/etcd/client/pkg/v3/transport go.etcd.io/etcd/client/pkg/v3/types -# go.etcd.io/etcd/client/v3 v3.5.17 +# go.etcd.io/etcd/client/v3 v3.5.18 ## explicit; go 1.22 go.etcd.io/etcd/client/v3 go.etcd.io/etcd/client/v3/credentials @@ -1159,7 +1162,7 @@ go.opencensus.io/trace/tracestate ## explicit; go 1.22.0 go.opentelemetry.io/auto/sdk go.opentelemetry.io/auto/sdk/internal/telemetry -# go.opentelemetry.io/collector/pdata v1.22.0 +# go.opentelemetry.io/collector/pdata v1.24.0 ## explicit; go 1.22.0 go.opentelemetry.io/collector/pdata/internal go.opentelemetry.io/collector/pdata/internal/data @@ -1194,7 +1197,7 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvut # go.opentelemetry.io/contrib/propagators/autoprop v0.54.0 ## explicit; go 1.21 go.opentelemetry.io/contrib/propagators/autoprop -# go.opentelemetry.io/contrib/propagators/aws v1.33.0 +# go.opentelemetry.io/contrib/propagators/aws v1.34.0 ## explicit; go 1.22.0 go.opentelemetry.io/contrib/propagators/aws/xray # go.opentelemetry.io/contrib/propagators/b3 v1.29.0 @@ -1206,7 +1209,7 @@ go.opentelemetry.io/contrib/propagators/jaeger # go.opentelemetry.io/contrib/propagators/ot v1.29.0 ## explicit; go 1.21 go.opentelemetry.io/contrib/propagators/ot -# go.opentelemetry.io/otel v1.33.0 +# go.opentelemetry.io/otel v1.34.0 ## explicit; go 1.22.0 go.opentelemetry.io/otel go.opentelemetry.io/otel/attribute @@ -1223,27 +1226,27 @@ go.opentelemetry.io/otel/semconv/v1.17.0/httpconv go.opentelemetry.io/otel/semconv/v1.20.0 go.opentelemetry.io/otel/semconv/v1.21.0 go.opentelemetry.io/otel/semconv/v1.26.0 -# go.opentelemetry.io/otel/bridge/opentracing v1.33.0 +# go.opentelemetry.io/otel/bridge/opentracing v1.34.0 ## explicit; go 1.22.0 go.opentelemetry.io/otel/bridge/opentracing go.opentelemetry.io/otel/bridge/opentracing/migration -# go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 -## explicit; go 1.22.7 +# go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 +## explicit; go 1.22.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform -# go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 -## explicit; go 1.22.7 +# go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 +## explicit; go 1.22.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/envconfig go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/retry -# go.opentelemetry.io/otel/metric v1.33.0 +# go.opentelemetry.io/otel/metric v1.34.0 ## explicit; go 1.22.0 go.opentelemetry.io/otel/metric go.opentelemetry.io/otel/metric/embedded go.opentelemetry.io/otel/metric/noop -# go.opentelemetry.io/otel/sdk v1.33.0 +# go.opentelemetry.io/otel/sdk v1.34.0 ## explicit; go 1.22.0 go.opentelemetry.io/otel/sdk go.opentelemetry.io/otel/sdk/instrumentation @@ -1252,13 +1255,13 @@ go.opentelemetry.io/otel/sdk/internal/x go.opentelemetry.io/otel/sdk/resource go.opentelemetry.io/otel/sdk/trace go.opentelemetry.io/otel/sdk/trace/tracetest -# go.opentelemetry.io/otel/trace v1.33.0 +# go.opentelemetry.io/otel/trace v1.34.0 ## explicit; go 1.22.0 go.opentelemetry.io/otel/trace go.opentelemetry.io/otel/trace/embedded go.opentelemetry.io/otel/trace/noop -# go.opentelemetry.io/proto/otlp v1.4.0 -## explicit; go 1.22.7 +# go.opentelemetry.io/proto/otlp v1.5.0 +## explicit; go 1.22.0 go.opentelemetry.io/proto/otlp/collector/trace/v1 go.opentelemetry.io/proto/otlp/common/v1 go.opentelemetry.io/proto/otlp/resource/v1 @@ -1288,7 +1291,7 @@ go4.org/intern # go4.org/unsafe/assume-no-moving-gc v0.0.0-20230525183740-e7c30c78aeb2 ## explicit; go 1.11 go4.org/unsafe/assume-no-moving-gc -# golang.org/x/crypto v0.31.0 +# golang.org/x/crypto v0.32.0 ## explicit; go 1.20 golang.org/x/crypto/argon2 golang.org/x/crypto/bcrypt @@ -1307,10 +1310,10 @@ golang.org/x/crypto/pkcs12/internal/rc2 ## explicit; go 1.20 golang.org/x/exp/constraints golang.org/x/exp/slices -# golang.org/x/mod v0.21.0 +# golang.org/x/mod v0.22.0 ## explicit; go 1.22.0 golang.org/x/mod/semver -# golang.org/x/net v0.33.0 +# golang.org/x/net v0.34.0 ## explicit; go 1.18 golang.org/x/net/bpf golang.org/x/net/context @@ -1346,7 +1349,7 @@ golang.org/x/oauth2/jwt golang.org/x/sync/errgroup golang.org/x/sync/semaphore golang.org/x/sync/singleflight -# golang.org/x/sys v0.28.0 +# golang.org/x/sys v0.29.0 ## explicit; go 1.18 golang.org/x/sys/cpu golang.org/x/sys/unix @@ -1365,14 +1368,15 @@ 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.8.0 +# golang.org/x/time v0.9.0 ## explicit; go 1.18 golang.org/x/time/rate -# golang.org/x/tools v0.24.0 -## explicit; go 1.19 +# golang.org/x/tools v0.28.0 +## explicit; go 1.22.0 golang.org/x/tools/go/gcexportdata golang.org/x/tools/go/packages golang.org/x/tools/go/types/objectpath +golang.org/x/tools/go/types/typeutil golang.org/x/tools/internal/aliases golang.org/x/tools/internal/event golang.org/x/tools/internal/event/core @@ -1383,7 +1387,7 @@ golang.org/x/tools/internal/gocommand 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 # gonum.org/v1/gonum v0.15.0 @@ -1413,17 +1417,17 @@ google.golang.org/api/transport/http/internal/propagation ## explicit; go 1.21 google.golang.org/genproto/googleapis/type/date google.golang.org/genproto/googleapis/type/expr -# google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 -## explicit; go 1.21 +# google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f +## explicit; go 1.22 google.golang.org/genproto/googleapis/api google.golang.org/genproto/googleapis/api/annotations google.golang.org/genproto/googleapis/api/httpbody -# google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 -## explicit; go 1.21 +# google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f +## explicit; go 1.22 google.golang.org/genproto/googleapis/rpc/code google.golang.org/genproto/googleapis/rpc/errdetails google.golang.org/genproto/googleapis/rpc/status -# google.golang.org/grpc v1.68.1 => google.golang.org/grpc v1.65.0 +# google.golang.org/grpc v1.69.4 => google.golang.org/grpc v1.65.0 ## explicit; go 1.21 google.golang.org/grpc google.golang.org/grpc/attributes @@ -1493,7 +1497,7 @@ google.golang.org/grpc/stats google.golang.org/grpc/status google.golang.org/grpc/tap google.golang.org/grpc/test/bufconn -# google.golang.org/protobuf v1.36.1 +# google.golang.org/protobuf v1.36.3 ## explicit; go 1.21 google.golang.org/protobuf/encoding/protodelim google.golang.org/protobuf/encoding/protojson @@ -1540,8 +1544,8 @@ google.golang.org/protobuf/types/known/wrapperspb # gopkg.in/alecthomas/kingpin.v2 v2.2.6 => github.com/alecthomas/kingpin v1.3.8-0.20210301060133-17f40c25f497 ## explicit; go 1.13 gopkg.in/alecthomas/kingpin.v2 -# gopkg.in/telebot.v3 v3.2.1 -## explicit; go 1.13 +# gopkg.in/telebot.v3 v3.3.8 +## explicit; go 1.16 gopkg.in/telebot.v3 # gopkg.in/yaml.v2 v2.4.0 ## explicit; go 1.15